[SSI] openssi/kernel/cluster/ssi/util load_level.c, 1.25, 1.26 nfs_mount.c, 1.13, 1.14 rcopy.c, 1.13, 1.14 rmtfb.c, 1.24, 1.25 ssipty.c, 1.15, 1.16
Roger Tsang <[email protected]>
| Newsgroups | gmane.linux.cluster.ssic.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util
In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv1388/cluster/ssi/util
Modified Files:
Tag: OPENSSI-FC
load_level.c nfs_mount.c rcopy.c rmtfb.c ssipty.c
Log Message:
Multiple bug fixes. See ChangeLog.
Index: nfs_mount.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/nfs_mount.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- nfs_mount.c 27 Oct 2009 03:18:29 -0000 1.13
+++ nfs_mount.c 17 Dec 2009 06:43:51 -0000 1.14
@@ -409,6 +409,7 @@
struct nfs_vfsmount_data *cmdp;
int p_len;
+ *type = NULL;
*payload = NULL;
p_len = sizeof(struct nfs_vfsmount_data);
@@ -425,6 +426,7 @@
*payload = kmalloc(*payload_len, GFP_KERNEL);
if (*payload == NULL) {
kfree(*type);
+ *type = NULL;
return -ENOMEM;
}
Index: ssipty.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/ssipty.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- ssipty.c 27 Oct 2009 03:18:29 -0000 1.15
+++ ssipty.c 17 Dec 2009 06:43:51 -0000 1.16
@@ -1199,6 +1199,7 @@
umode_t mode;
int p_len;
+ *type = NULL;
*payload = NULL;
/* Ignore local only vfsmount */
@@ -1219,6 +1220,7 @@
*payload = kmalloc(*payload_len, GFP_KERNEL);
if (*payload == NULL) {
kfree(*type);
+ *type = NULL;
return -ENOMEM;
}
@@ -1243,8 +1245,13 @@
ssipty_get_mntopts(&setuid, &uid, &setgid, &gid, &mode);
ret = ssipty_build_mntopts(cmap, cmap_len, setuid, uid, setgid, gid,
mode);
- if (ret < 0)
+ if (ret < 0) {
+ kfree(*payload);
+ *payload = NULL;
+ kfree(*type);
+ *type = NULL;
return ret;
+ }
return 0;
}
Index: load_level.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/load_level.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- load_level.c 17 Nov 2009 06:09:02 -0000 1.25
+++ load_level.c 17 Dec 2009 06:43:51 -0000 1.26
@@ -806,11 +806,7 @@
else {
#endif /* !LOADLEVEL_TABLE_LIST */
/* get process executable from its memory */
- task_lock(p);
- mm = p->mm;
- if (mm)
- atomic_inc(&mm->mm_users);
- task_unlock(p);
+ mm = get_task_mm(p);
if (!mm)
return 0;
@@ -821,13 +817,14 @@
vma = mm->mmap;
while (vma) {
if ((vma->vm_flags & VM_EXECUTABLE) &&
- vma->vm_file) {
- mnt = mntget(vma->vm_file->f_vfsmnt);
- dentry = dget(vma->vm_file->f_dentry);
+ vma->vm_file)
break;
- }
vma = vma->vm_next;
}
+ if (vma) {
+ mnt = mntget(vma->vm_file->f_vfsmnt);
+ dentry = dget(vma->vm_file->f_dentry);
+ }
up_read(&mm->mmap_sem);
mmput(mm);
}
Index: rmtfb.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/rmtfb.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- rmtfb.c 27 Oct 2009 03:18:29 -0000 1.24
+++ rmtfb.c 17 Dec 2009 06:43:51 -0000 1.25
@@ -107,18 +107,28 @@
* Support Routines
*/
-static inline struct inode *
-ftoi(struct file *file)
-{
- return file->f_dentry->d_inode;
-}
+#define GET_RFB(_rfb) atomic_inc(&(_rfb)->rfb_refcnt)
-static inline struct rmtfb_cli *
+#define ftoi(_fp) ((_fp)->f_dentry->d_inode)
+
+#ifndef RMTFB_REFCNT_FIX
+static inline
+#endif
+struct rmtfb_cli *
ftocli(struct file *file)
{
- struct rmtfb_cli *rfb = (struct rmtfb_cli *)file->private_data;
- rfb = (rfb && rfb->rfb_magic == rmtfb_magic) ? rfb : NULL;
- SSI_ASSERT(!rfb || rfb->common.rfb_file == file);
+ struct rmtfb_cli *rfb;
+
+ if (!file->private_data)
+ return NULL;
+
+ rfb = (struct rmtfb_cli *)file->private_data;
+ SSI_ASSERT(rfb);
+ if (!rfb)
+ return NULL;
+ if (rfb->rfb_magic != rmtfb_magic)
+ return NULL;
+ SSI_ASSERT(rfb->common.rfb_file == file);
return rfb;
}
@@ -174,6 +184,18 @@
kfree(rfb);
}
+#ifdef RMTFB_REFCNT_FIX
+static inline void
+rmtfb_freecli(struct rmtfb_cli *rfb)
+{
+ /* SSI: We skipped struct file reference to avoid circular reference.
+ * file->private_data->common.rfb_file == file
+ */
+ /* fput(rfb->common.rfb_file); */
+ rfb->rfb_magic = 0;
+ kfree(rfb);
+}
+#endif
/*
* Client Bitmap
@@ -184,31 +206,35 @@
rmtfb_set_bit(clusternode_t cli, struct rmtfb_svr *rfb, int set)
{
SSI_ASSERT(cli && !inval(1,cli));
- if (set) {
#ifdef RMTFB_REFCNT_FIX
- atomic_inc(&rfb->rfb_refcnt);
-#endif
+ if (set) {
+ if (!test_and_set_bit(cli - 1, rfb->rfb_clients))
+ GET_RFB(rfb);
+ } else {
+ if (test_and_clear_bit(cli - 1, rfb->rfb_clients))
+ rmtfb_putsvr(rfb);
+ }
+#else
+ if (set) {
set_bit(cli - 1, &rfb->rfb_clients[0]);
} else {
clear_bit(cli - 1, &rfb->rfb_clients[0]);
-#ifdef RMTFB_REFCNT_FIX
- rmtfb_putsvr(rfb);
-#endif
}
+#endif /* !RMTFB_REFCNT_FIX */
}
+#ifndef RMTFB_REFCNT_FIX
static inline int
rmtfb_nocli(struct rmtfb_svr *rfb)
{
-#ifndef RMTFB_REFCNT_FIX
int ctr = 0;
volatile unsigned long *word = rfb->rfb_clients;
for (; ctr < rfb_clients_len; ++ctr, ++word)
if (*word)
return 0;
-#endif
return 1;
}
+#endif
int
rmtfb_setopen(
@@ -246,6 +272,7 @@
}
rmtfb_putsvr(rfb);
error = 0;
+ /* file already held by rfb */
file_out:
fput(file);
out:
@@ -467,11 +494,16 @@
static void
rmtfb_clrnode(struct rmtfb_cmn *cmn, u_long arg)
{
+ struct rmtfb_svr *rfb = (struct rmtfb_svr *)cmn;
struct rmtfb_clrnode_arg *ap = (void *)arg;
- struct rmtfb_svr *rfb = (struct rmtfb_svr *)cmn;
+#ifdef RMTFB_REFCNT_FIX
+ if (test_bit(ap->node - 1, rfb->rfb_clients)) {
+ GET_RFB(rfb);
+ list_move(&rfb->common.rfb_hash, ap->list);
+ }
+#else
rmtfb_set_bit(ap->node, rfb, 0);
-#ifndef RMTFB_REFCNT_FIX
if (!atomic_read(&rfb->rfb_refcnt) && rmtfb_nocli(rfb))
list_move(&rfb->common.rfb_hash, ap->list);
#endif
@@ -507,11 +539,13 @@
clusternode_t surrogate,
void *private)
{
-#ifndef RMTFB_REFCNT_FIX
+#ifdef RMTFB_REFCNT_FIX
+ struct rmtfb_svr *rfb, *tmp;
+#else
struct list_head *cur;
+#endif
LIST_HEAD(freelist);
struct rmtfb_clrnode_arg rca;
-#endif
SSI_ASSERT(node && !inval(1,node));
@@ -521,17 +555,18 @@
rmtfb_nodedown_cmn(rmtfb_clitbl, rmtfb_badops, (u_long)node);
UNLOCK_SHR_RW_LOCK(&rmtfb_clitbl_lock);
-#ifdef RMTFB_REFCNT_FIX
- LOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
- rmtfb_nodedown_cmn(rmtfb_svrtbl, rmtfb_clrnode, 0);
- UNLOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
-#else
rca.node = node;
rca.list = &freelist;
LOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
rmtfb_nodedown_cmn(rmtfb_svrtbl, rmtfb_clrnode, (u_long)&rca);
UNLOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
+#ifdef RMTFB_REFCNT_FIX
+ list_for_each_entry_safe(rfb, tmp, &freelist, common.rfb_hash) {
+ rmtfb_set_bit(node, rfb, 0);
+ rmtfb_putsvr(rfb);
+ }
+#else
list_for_each(cur, &freelist) {
struct rmtfb_svr *rfb = (struct rmtfb_svr *)
list_entry(cur, struct rmtfb_cmn, rfb_hash);
@@ -584,19 +619,21 @@
void *data)
{
struct rmtfb_svr *rfb;
+
#ifdef RFBDEBUG
printk(KERN_DEBUG "rmtfb_getsvr: pid=%d searching for ino=%lu\n",
current->pid, ino);
#endif
SSI_ASSERT_LOCKED_SHR_RW_LOCK(&rmtfb_svrtbl_lock);
+
rfb = (struct rmtfb_svr *) rmtfb_getcmn(
&rmtfb_svrtbl[hash(ino)],
test,
data);
if (rfb)
- atomic_inc(&rfb->rfb_refcnt);
- SSI_ASSERT(!rfb || atomic_read(&rfb->rfb_refcnt));
+ GET_RFB(rfb);
#ifdef RFBDEBUG
+ SSI_ASSERT(!rfb || atomic_read(&rfb->rfb_refcnt));
rmtfb_svr_debug("rmtfb_getsvr:",rfb);
#endif
return rfb;
@@ -605,18 +642,26 @@
struct rmtfb_svr *
rmtfb_getsvr_file(struct file *file)
{
- struct rmtfb_svr *rfb = NULL;
+ struct rmtfb_svr *rfb;
+
SSI_ASSERT(file);
+
+#ifndef RMTFB_REFCNT_FIX
if (atomic_read(&file->f_count) > 1) {
+#endif
LOCK_SHR_RW_LOCK(&rmtfb_svrtbl_lock);
rfb = rmtfb_getsvr(
ftoi(file)->i_ino,
rmtfb_test_file,
(void *)file);
UNLOCK_SHR_RW_LOCK(&rmtfb_svrtbl_lock);
- }
+#ifndef RMTFB_REFCNT_FIX
+ } else
+ rfb = NULL;
+#endif
if (!rfb)
rfb = rmtfb_newsvr(file, 0, 0);
+
SSI_ASSERT(rfb);
SSI_ASSERT(IS_ERR(rfb) || rfb->common.rfb_file == file);
return rfb;
@@ -677,14 +722,11 @@
#ifndef RMTFB_REFCNT_FIX
/* SSI_XXX: does rfb_refcnt go negative when !rmtfb_nocli() ? */
SSI_ASSERT(atomic_read(&rfb->rfb_refcnt));
-#endif
LOCK_SHR_RW_LOCK(&rmtfb_svrtbl_lock);
if (atomic_dec_and_test(&rfb->rfb_refcnt) && rmtfb_nocli(rfb)) {
atomic_inc(&rfb->rfb_refcnt);
UNLOCK_SHR_RW_LOCK(&rmtfb_svrtbl_lock);
-#ifndef RMTFB_REFCNT_FIX
SSI_ASSERT(atomic_read(&rfb->rfb_refcnt));
-#endif
LOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
if (atomic_dec_and_test(&rfb->rfb_refcnt) && rmtfb_nocli(rfb)) {
list_del(&rfb->common.rfb_hash);
@@ -696,15 +738,40 @@
}
else
UNLOCK_SHR_RW_LOCK(&rmtfb_svrtbl_lock);
+#else /* !RMTFB_REFCNT_FIX */
+ LOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
+ if (!atomic_dec_and_test(&rfb->rfb_refcnt)) {
+ UNLOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
+ return;
+ }
+ list_del(&rfb->common.rfb_hash);
+ UNLOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
+ rmtfb_freesvr(rfb);
+#endif /* RMTFB_REFCNT_FIX */
}
struct rmtfb_cli *
rmtfb_getcli_file(struct file *file)
{
+#ifdef RMTFB_REFCNT_FIX
+ struct rmtfb_cli *rfb;
+#endif
+
if (file->f_op != &ssidev_remote_fops && file->f_op != &ssidev_bad_fops)
return NULL;
+#ifdef RMTFB_REFCNT_FIX
+ rfb = ftocli(file);
+ if (!rfb)
+ return NULL;
+
+ /* No race here. file->private_data has rfb reference */
+ GET_RFB(rfb);
+
+ return rfb;
+#else
return ftocli(file);
+#endif /* !RMTFB_REFCNT_FIX */
}
static inline struct rmtfb_cli *
@@ -718,12 +785,22 @@
&rmtfb_clitbl[hash(id)],
rmtfb_test_id,
(void *)&id);
+#ifdef RMTFB_REFCNT_FIX
+ if (rfb) {
+ SSI_ASSERT(rfb->common.rfb_id == id);
+ if (!atomic_test_and_add(1, &rfb->common.rfb_file->f_count)) {
+ /* Lost race with fput() */
+ return ERR_PTR(-ERFB_RELEASE);
+ }
+ GET_RFB(rfb);
+ }
+#else
SSI_ASSERT(!rfb || rfb->common.rfb_id == id);
if (rfb && !atomic_test_and_add(1, &rfb->common.rfb_file->f_count))
rfb = ERR_PTR(-ERFB_RELEASE);
else
SSI_ASSERT(!rfb || atomic_read(&rfb->common.rfb_file->f_count));
-
+#endif
return rfb;
}
@@ -793,8 +870,8 @@
}
/* make socket back pointer */
- if (file->f_dentry->d_inode->i_sock) {
- struct socket *sock = SOCKET_I(file->f_dentry->d_inode);
+ if (ftoi(file)->i_sock) {
+ struct socket *sock = SOCKET_I(ftoi(file));
sock->file = file;
#ifdef SSI_SOCK_REOP_TYPE
sock->type = socket_type;
@@ -803,24 +880,39 @@
sock->ssi_rfb_svr = svr;
}
- rfb = ERR_PTR(-EOPNOTSUPP);
if (file->private_data) {
printk(KERN_ERR
"rmtfb_getcli_id: non-exportable filesystem (%s)\n",
file->f_vfsmnt->mnt_sb->s_type->name);
- put_filp(file);
+ fput(file);
+ rfb = ERR_PTR(-EOPNOTSUPP);
goto out;
}
rfb = rmtfb_newcli(file, id, svr, 0);
if (IS_ERR(rfb))
- put_filp(file);
+ fput(file);
out:
SSI_ASSERT(rfb);
SSI_ASSERT(IS_ERR(rfb) || rfb->common.rfb_id == id);
return rfb;
}
+#ifdef RMTFB_REFCNT_FIX
+void rmtfb_putcli(struct rmtfb_cli *rfb)
+{
+ BUG_ON(rfb->rfb_magic != rmtfb_magic);
+ LOCK_EXCL_RW_LOCK(&rmtfb_clitbl_lock);
+ if (!atomic_dec_and_test(&rfb->rfb_refcnt)) {
+ UNLOCK_EXCL_RW_LOCK(&rmtfb_clitbl_lock);
+ return;
+ }
+ list_del(&rfb->common.rfb_hash);
+ UNLOCK_EXCL_RW_LOCK(&rmtfb_clitbl_lock);
+ rmtfb_freecli(rfb);
+}
+#endif
+
/*
* Constructors/Destructors
@@ -830,14 +922,16 @@
rmtfb_new_prep(struct file *file, unsigned long id, size_t size)
{
struct rmtfb_cmn *cmn;
+
SSI_ASSERT(file);
SSI_ASSERT(size > sizeof(*cmn));
+
cmn = kzmalloc(size, GFP_USER);
if (!cmn)
return NULL;
INIT_LIST_HEAD(&cmn->rfb_hash);
- cmn->rfb_file = file;
+ cmn->rfb_file = file; /* Caller to grab reference to file */
cmn->rfb_id = id ? id : unum_getnum(unum_rmtfbid);
return cmn;
}
@@ -848,19 +942,20 @@
struct rmtfb_svr *rfb, *newrfb;
unsigned long ino = ftoi(file)->i_ino;
char export = id ? 0 : 1;
- int error;
+ int error = -ENOMEM;
- SSI_ASSERT(file);
SSI_ASSERT(!inval(1,cli));
- error = -ENOMEM;
+
newrfb = (struct rmtfb_svr *)rmtfb_new_prep(file, id, sizeof(*rfb));
if (!newrfb)
goto fail;
+
atomic_set(&newrfb->rfb_refcnt, 1);
if (cli)
rmtfb_set_bit(cli, newrfb, 1);
LOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
+
SSI_ASSERT(!ftocli(file));
if (export) {
/* make sure another export didn't make one already */
@@ -877,6 +972,7 @@
rmtfb_svr_debug("rmtfb_newsvr:",rfb);
#endif
return rfb;
+
unlock_free_out:
UNLOCK_EXCL_RW_LOCK(&rmtfb_svrtbl_lock);
kfree(newrfb);
@@ -935,14 +1031,17 @@
char import = id ? 1 : 0;
int error, loop = 0;
- SSI_ASSERT(file);
SSI_ASSERT(svr && !inval(1,svr));
error = -ENOMEM;
newrfb = (struct rmtfb_cli *)rmtfb_new_prep(file, id, sizeof(*rfb));
if (!newrfb)
goto fail;
+
id = newrfb->common.rfb_id;
+#ifdef RMTFB_REFCNT_FIX
+ atomic_set(&newrfb->rfb_refcnt, 1);
+#endif
newrfb->rfb_magic = rmtfb_magic;
newrfb->rfb_server = svr;
@@ -975,8 +1074,15 @@
}
if (rfb) {
UNLOCK_EXCL_RW_LOCK(&rmtfb_clitbl_lock);
+#ifdef RMTFB_REFCNT_FIX
+ rmtfb_freecli(newrfb);
+ /* Release reference in rmtfb_getcli_id_lckd() */
+ SSI_ASSERT(rfb->common.rfb_file == file);
+ fput(rfb->common.rfb_file);
+#else
kfree(newrfb);
put_filp(file);
+#endif
goto out;
}
}
@@ -984,10 +1090,20 @@
if (!noremote)
rmtfb_remote_tty_ino(file, svr);
#endif
+ /* SSI_XXX: overrides struct socket->file->f_op */
file->f_op = &ssidev_remote_fops;
file->private_data = rfb = newrfb;
+#ifdef RMTFB_REFCNT_FIX
+ /* SSI: fifo_open() will override f_op.
+ * free_pipe_info() will release rfb reference.
+ */
+ GET_RFB(rfb); /* for file->private_data */
+#endif
list_add(&rfb->common.rfb_hash, &rmtfb_clitbl[hash(id)]);
SSI_ASSERT(ftocli(file) == rfb);
+ /* Skipped get_file(file) due to circular reference.
+ * file->private_data->common.rfb_file == file
+ */
UNLOCK_EXCL_RW_LOCK(&rmtfb_clitbl_lock);
error = 0;
out:
@@ -996,8 +1112,13 @@
rmtfb_cli_debug("rmtfb_newcli:",rfb);
#endif
return rfb;
+
free_fail:
+#ifdef RMTFB_REFCNT_FIX
+ rmtfb_freecli(newrfb);
+#else
kfree(newrfb);
+#endif
fail:
#ifdef RFBDEBUG
printk(KERN_DEBUG "rmtfb_newcli: fail error=%d ino=%lu name=%s", error,
@@ -1016,7 +1137,16 @@
current->pid, file, svr);
#endif
rfb = rmtfb_newcli(file, 0, svr, 0);
+#ifdef RMTFB_REFCNT_FIX
+ if (IS_ERR(rfb))
+ return PTR_ERR(rfb);
+
+ rmtfb_putcli(rfb);
+ /* rfb is still held by file->private_data */
+ return 0;
+#else
return IS_ERR(rfb) ? PTR_ERR(rfb) : 0;
+#endif
}
int
@@ -1047,11 +1177,17 @@
rmtfb_cli_debug("rmtfb_rclose:",rfb);
#endif /* RFBDEBUG */
+#ifdef RMTFB_REFCNT_FIX
+ file->private_data = NULL;
+ /* Release file->private_data */
+ rmtfb_putcli(rfb);
+#else
LOCK_EXCL_RW_LOCK(&rmtfb_clitbl_lock);
list_del(&rfb->common.rfb_hash);
UNLOCK_EXCL_RW_LOCK(&rmtfb_clitbl_lock);
rfb->rfb_magic = 0;
kfree(rfb);
+#endif /* !RMTFB_REFCNT_FIX */
return error;
}
Index: rcopy.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/util/rcopy.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- rcopy.c 27 Oct 2009 03:18:29 -0000 1.13
+++ rcopy.c 17 Dec 2009 06:43:51 -0000 1.14
@@ -54,40 +54,42 @@
static int ssi_rcopy_strnlen_task(struct task_struct *p, u_long from, u_long *n)
{
- int error = 0;
char *cbuf;
u_long nbytes;
- int copy;
- int copied;
- int len;
+ int error;
+ int copy, copied, len;
nbytes = *n;
*n = 0;
+
cbuf = (char *)__get_free_page(GFP_USER);
- if (cbuf != NULL) {
- while (nbytes > 0) {
- if (nbytes > PAGE_SIZE)
- copy = PAGE_SIZE;
- else
- copy = nbytes;
- copied = access_process_vm(p, from, cbuf, copy, 0);
- if (copied > 0) {
- len = strnlen(cbuf, copied);
- *n += len;
- if (len < copied)
- break;
- }
- if (copied != copy) {
- error = -EFAULT;
+ if (!cbuf)
+ return -ENOMEM;
+
+ error = 0;
+ copy = PAGE_SIZE;
+ while (nbytes > 0) {
+ if (nbytes < PAGE_SIZE)
+ copy = nbytes;
+
+ copied = access_process_vm(p, from, cbuf, copy, 0);
+ if (copied > 0) {
+ len = strnlen(cbuf, copied);
+ *n += len;
+ if (len < copied)
break;
- }
- from += copied;
- nbytes -= copied;
}
- free_page((u_long)cbuf);
- (*n)++;
- } else
- error = -ENOMEM;
+ if (copied != copy) {
+ error = -EFAULT;
+ break;
+ }
+ from += copied;
+ nbytes -= copied;
+ }
+ rmb(); /* control dependency */
+ (*n)++;
+
+ free_page((u_long)cbuf);
return error;
}
@@ -98,17 +100,64 @@
register struct vproc *v = VPROCPTR(pid);
struct task_struct *p;
int copied;
+#ifdef TASK_HOLD_VPROC
+ void *buf;
+#endif
SSI_ASSERT(v != NULL);
SSI_ASSERT(*data_len > 0);
SSI_ASSERT(*data_len <= ICS_MAX_OOL_DATA_SIZE);
+
+#ifdef TASK_HOLD_VPROC
+ if (unlikely(v == NULL)) {
+ *rerror = -ESRCH;
+ *data_len = 0;
+ return 0;
+ }
+
+ VPROC_LOCK_FLAG(v, "rssi_rcopy_from_user");
+
+ if (unlikely(!(PVP(v)->pvp_flag & PV_IS_LOCAL))) {
+ /* Process migrated */
+ VPROC_UNLOCK_FLAG(v, "rssi_rcopy_from_user");
+ *rerror = -ESRCH;
+ *data_len = 0;
+ p = NULL;
+ goto out;
+ }
+ p = PVP(v)->pvp_pproc;
+ get_task_struct(p);
+ VPROC_UNLOCK_FLAG(v, "rssi_rcopy_from_user");
+
+ buf = *data;
+ if (!buf) {
+ buf = kmalloc(*data_len, GFP_USER);
+ if (buf == NULL) {
+ *rerror = -ENOMEM;
+ *data_len = 0;
+ goto out;
+ }
+ *data = buf;
+ }
+
+ /* Caller responsible for range check */
+ copied = access_process_vm(p, from, buf, *data_len, 0);
+ if (copied != *data_len) {
+ *data_len = copied;
+ *rerror = -EFAULT;
+ } else
+ *rerror = 0;
+
+out:
+ if (p)
+ put_task_struct(p);
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+ VPROC_RELE(v, "rssi_rcopy_from_user");
+#endif
+#else /* TASK_HOLD_VPROC */
if (v != NULL) {
p = PVP(v)->pvp_pproc;
-#ifdef TASK_HOLD_VPROC
- SSI_ASSERT(PVP(v)->pvp_flag & PV_IS_LOCAL);
-#else
SSI_ASSERT(p != NULL);
-#endif
}
else
p = NULL;
@@ -135,6 +184,7 @@
if (v)
VPROC_RELE(v, "rssi_rcopy_from_user");
#endif
+#endif /* !TASK_HOLD_VPROC */
return 0;
}
@@ -151,13 +201,43 @@
SSI_ASSERT(data != NULL);
SSI_ASSERT(data_len > 0);
SSI_ASSERT(data_len <= ICS_MAX_OOL_DATA_SIZE);
+
+#ifdef TASK_HOLD_VPROC
+ if (unlikely(v == NULL))
+ goto out_bad;
+
+ VPROC_LOCK_FLAG(v, "rssi_rcopy_to_user");
+
+ if (unlikely(!(PVP(v)->pvp_flag & PV_IS_LOCAL))) {
+ /* Process migrated */
+ VPROC_UNLOCK_FLAG(v, "rssi_rcopy_to_user");
+ goto out_bad;
+ }
+ p = PVP(v)->pvp_pproc;
+ get_task_struct(p);
+ VPROC_UNLOCK_FLAG(v, "rssi_rcopy_to_user");
+
+ /* Caller responsible for range check */
+ copied = access_process_vm(p, to, data, data_len, 1);
+ *n = data_len - copied;
+ if (*n != 0)
+ *rerror = -EFAULT;
+ else
+ *rerror = 0;
+
+ put_task_struct(p);
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+ VPROC_RELE(v, "rssi_rcopy_to_user");
+#endif
+ return 0;
+
+out_bad:
+ *rerror = -ESRCH;
+ *n = data_len;
+#else /* TASK_HOLD_VPROC */
if (v != NULL) {
p = PVP(v)->pvp_pproc;
-#ifdef TASK_HOLD_VPROC
- SSI_ASSERT(PVP(v)->pvp_flag & PV_IS_LOCAL);
-#else
SSI_ASSERT(p != NULL);
-#endif
}
else
p = NULL;
@@ -176,6 +256,7 @@
if (v)
VPROC_RELE(v, "rssi_rcopy_to_user");
#endif
+#endif /* !TASK_HOLD_VPROC */
return 0;
}
@@ -191,13 +272,51 @@
SSI_ASSERT(v != NULL);
SSI_ASSERT(*data_len > 0);
SSI_ASSERT(*data_len <= ICS_MAX_OOL_DATA_SIZE);
+
+#ifdef TASK_HOLD_VPROC
+ if (unlikely(v == NULL))
+ goto out_bad;
+
+ VPROC_LOCK_FLAG(v, "rssi_rcopy_strncpy_from_user");
+
+ if (unlikely(!(PVP(v)->pvp_flag & PV_IS_LOCAL))) {
+ VPROC_UNLOCK_FLAG(v, "rssi_rcopy_strncpy_from_user");
+ /* Process migrated */
+ goto out_bad;
+ }
+ p = PVP(v)->pvp_pproc;
+ get_task_struct(p);
+ VPROC_UNLOCK_FLAG(v, "rssi_rcopy_strncpy_from_user");
+
+ tmpn = *data_len;
+ smp_mb(); /* ensure tmpn value is visible */
+
+ *rerror = ssi_rcopy_strnlen_task(p, from, &tmpn);
+ if (*rerror >= 0) {
+ if (tmpn < *data_len)
+ *data_len = tmpn ;
+ (void)rssi_rcopy_from_user(to_node, rerror, pid,
+ from, data, data_len);
+ } else
+ *data_len = 0;
+
+ put_task_struct(p);
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+ VPROC_RELE(v, "rssi_rcopy_strncpy_from_user");
+#endif
+ return 0;
+
+out_bad:
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+ if (v)
+ VPROC_RELE(v, "rssi_rcopy_strncpy_from_user");
+#endif
+ *rerror = -ESRCH;
+ *data_len = 0;
+#else /* TASK_HOLD_VPROC */
if (v != NULL) {
p = PVP(v)->pvp_pproc;
-#ifdef TASK_HOLD_VPROC
- SSI_ASSERT(PVP(v)->pvp_flag & PV_IS_LOCAL);
-#else
SSI_ASSERT(p != NULL);
-#endif
}
else
p = NULL;
@@ -219,6 +338,7 @@
if (v)
VPROC_RELE(v, "rssi_rcopy_strncpy_from_user");
#endif
+#endif /* !TASK_HOLD_VPROC */
return 0;
}
@@ -232,13 +352,40 @@
SSI_ASSERT(v != NULL);
SSI_ASSERT(*n > 0);
SSI_ASSERT(*n <= ICS_MAX_OOL_DATA_SIZE);
+
+#ifdef TASK_HOLD_VPROC
+ if (unlikely(v == NULL))
+ goto out_bad;
+
+ VPROC_LOCK_FLAG(v, "rssi_rcopy_strnlen_user");
+
+ if (unlikely(!(PVP(v)->pvp_flag & PV_IS_LOCAL))) {
+ VPROC_UNLOCK_FLAG(v, "rssi_rcopy_strnlen_user");
+ /* Process migrated */
+ goto out_bad;
+ }
+ p = PVP(v)->pvp_pproc;
+ get_task_struct(p);
+ VPROC_UNLOCK_FLAG(v, "rssi_rcopy_strnlen_user");
+
+ *rerror = ssi_rcopy_strnlen_task(p, from, n);
+ put_task_struct(p);
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+ VPROC_RELE(v, "rssi_rcopy_strnlen_user");
+#endif
+ return 0;
+
+out_bad:
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+ if (v)
+ VPROC_RELE(v, "rssi_rcopy_strnlen_user");
+#endif
+ *rerror = -ESRCH;
+ (*n)++;
+#else /* TASK_HOLD_VPROC */
if (v != NULL) {
p = PVP(v)->pvp_pproc;
-#ifdef TASK_HOLD_VPROC
- SSI_ASSERT(PVP(v)->pvp_flag & PV_IS_LOCAL);
-#else
SSI_ASSERT(p != NULL);
-#endif
}
else
p = NULL;
@@ -252,6 +399,7 @@
if (v)
VPROC_RELE(v, "rssi_rcopy_strnlen_user");
#endif
+#endif /* !TASK_HOLD_VPROC */
return 0;
}
@@ -268,6 +416,55 @@
SSI_ASSERT(v != NULL);
SSI_ASSERT(*n > 0);
SSI_ASSERT(*n <= ICS_MAX_OOL_DATA_SIZE);
+
+#ifdef TASK_HOLD_VPROC
+ if (unlikely(v == NULL)) {
+ *rerror = -ESRCH;
+ goto out;
+ }
+
+ VPROC_LOCK_FLAG(v, "rssi_rcopy_clear_user");
+
+ if (unlikely(!(PVP(v)->pvp_flag & PV_IS_LOCAL))) {
+ VPROC_UNLOCK_FLAG(v, "rssi_rcopy_clear_user");
+ /* Process migrated */
+ *rerror = -ESRCH;
+ goto out;
+ }
+ p = PVP(v)->pvp_pproc;
+ get_task_struct(p);
+ VPROC_UNLOCK_FLAG(v, "rssi_rcopy_clear_user");
+
+ cbuf = (char *)get_zeroed_page(GFP_USER);
+ if (cbuf != NULL) {
+ *rerror = 0;
+ copy = PAGE_SIZE;
+ while (*n > 0) {
+ if (*n < PAGE_SIZE)
+ copy = *n;
+
+ copied = access_process_vm(p, to, cbuf, copy, 1);
+ if (copied > 0) {
+ *n -= copied;
+ to += copied;
+ }
+ if (copied != copy) {
+ *rerror = -EFAULT;
+ break;
+ }
+ }
+ free_page((u_long)cbuf);
+ }
+ else
+ *rerror = -ENOMEM;
+
+ put_task_struct(p);
+out:
+#ifdef VPROC_RELEASE__REFCNT_RACE_FIX
+ if (v)
+ VPROC_RELE(v, "rssi_rcopy_clear_user");
+#endif
+#else /* TASK_HOLD_VPROC */
if (v != NULL) {
p = PVP(v)->pvp_pproc;
#ifdef TASK_HOLD_VPROC
@@ -307,6 +504,7 @@
if (v)
VPROC_RELE(v, "rssi_rcopy_clear_user");
#endif
+#endif /* !TASK_HOLD_VPROC */
return 0;
}
@@ -359,6 +557,9 @@
break;
}
}
+
+ rmb(); /* control dependency */
+
/* Zero remaining buffer. */
if (*n > 0)
memset(t, 0, *n);
@@ -459,6 +660,7 @@
data_len = ICS_MAX_OOL_DATA_SIZE;
else
data_len = nbytes;
+
saved_len = data_len;
for (;;) {
if (to_node == this_node ||
@@ -494,7 +696,8 @@
if (data_len != saved_len)
break;
}
- if (*n > 0 && t[-1] == '\0')
+ rmb(); /* control dependency */
+ if (*n > 0 && *(t-1) == '\0')
(*n)--;
return error;
------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev