diff options
Diffstat (limited to 'ipc')
| -rw-r--r-- | ipc/compat.c | 18 | ||||
| -rw-r--r-- | ipc/mqueue.c | 119 | ||||
| -rw-r--r-- | ipc/shm.c | 9 | ||||
| -rw-r--r-- | ipc/syscall.c | 2 | ||||
| -rw-r--r-- | ipc/util.c | 4 | ||||
| -rw-r--r-- | ipc/util.h | 2 | 
6 files changed, 68 insertions, 86 deletions
diff --git a/ipc/compat.c b/ipc/compat.c index a6df704f521e..ad9518eb26e0 100644 --- a/ipc/compat.c +++ b/ipc/compat.c @@ -118,7 +118,7 @@ extern int sem_ctls[];  static inline int compat_ipc_parse_version(int *cmd)  { -#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC +#ifdef	CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION  	int version = *cmd & IPC_64;  	/* this is tricky: architectures that have support for the old @@ -373,21 +373,21 @@ long compat_sys_semctl(int semid, int semnum, int cmd, int arg)  }  long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp, -		       size_t msgsz, int msgflg) +		       compat_ssize_t msgsz, int msgflg)  {  	compat_long_t mtype;  	if (get_user(mtype, &msgp->mtype))  		return -EFAULT; -	return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg); +	return do_msgsnd(msqid, mtype, msgp->mtext, (ssize_t)msgsz, msgflg);  }  long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp, -		       size_t msgsz, long msgtyp, int msgflg) +		       compat_ssize_t msgsz, long msgtyp, int msgflg)  {  	long err, mtype; -	err =  do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg); +	err =  do_msgrcv(msqid, &mtype, msgp->mtext, (ssize_t)msgsz, msgtyp, msgflg);  	if (err < 0)  		goto out; @@ -514,6 +514,10 @@ long compat_sys_msgctl(int first, int second, void __user *uptr)  	return err;  } +#ifndef COMPAT_SHMLBA +#define COMPAT_SHMLBA	SHMLBA +#endif +  #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC  long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,  			void __user *uptr) @@ -524,7 +528,7 @@ long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,  	if (version == 1)  		return -EINVAL; -	err = do_shmat(first, uptr, second, &raddr); +	err = do_shmat(first, uptr, second, &raddr, COMPAT_SHMLBA);  	if (err < 0)  		return err;  	uaddr = compat_ptr(third); @@ -536,7 +540,7 @@ long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg)  	unsigned long ret;  	long err; -	err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret); +	err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret, COMPAT_SHMLBA);  	if (err)  		return err;  	force_successful_syscall_return(); diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 8ce57691e7b6..f8e54f5b9080 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -413,7 +413,7 @@ static void mqueue_evict_inode(struct inode *inode)  }  static int mqueue_create(struct inode *dir, struct dentry *dentry, -				umode_t mode, struct nameidata *nd) +				umode_t mode, bool excl)  {  	struct inode *inode;  	struct mq_attr *attr = dentry->d_fsdata; @@ -721,8 +721,8 @@ static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr)  /*   * Invoked when creating a new queue via sys_mq_open   */ -static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir, -			struct dentry *dentry, int oflag, umode_t mode, +static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir, +			struct path *path, int oflag, umode_t mode,  			struct mq_attr *attr)  {  	const struct cred *cred = current_cred(); @@ -732,9 +732,9 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,  	if (attr) {  		ret = mq_attr_ok(ipc_ns, attr);  		if (ret) -			goto out; +			return ERR_PTR(ret);  		/* store for use during create */ -		dentry->d_fsdata = attr; +		path->dentry->d_fsdata = attr;  	} else {  		struct mq_attr def_attr; @@ -744,71 +744,51 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,  					  ipc_ns->mq_msgsize_default);  		ret = mq_attr_ok(ipc_ns, &def_attr);  		if (ret) -			goto out; +			return ERR_PTR(ret);  	}  	mode &= ~current_umask(); -	ret = mnt_want_write(ipc_ns->mq_mnt); +	ret = mnt_want_write(path->mnt);  	if (ret) -		goto out; -	ret = vfs_create(dir->d_inode, dentry, mode, NULL); -	dentry->d_fsdata = NULL; -	if (ret) -		goto out_drop_write; - -	result = dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred); +		return ERR_PTR(ret); +	ret = vfs_create(dir, path->dentry, mode, true); +	path->dentry->d_fsdata = NULL; +	if (!ret) +		result = dentry_open(path, oflag, cred); +	else +		result = ERR_PTR(ret);  	/*  	 * dentry_open() took a persistent mnt_want_write(),  	 * so we can now drop this one.  	 */ -	mnt_drop_write(ipc_ns->mq_mnt); +	mnt_drop_write(path->mnt);  	return result; - -out_drop_write: -	mnt_drop_write(ipc_ns->mq_mnt); -out: -	dput(dentry); -	mntput(ipc_ns->mq_mnt); -	return ERR_PTR(ret);  }  /* Opens existing queue */ -static struct file *do_open(struct ipc_namespace *ipc_ns, -				struct dentry *dentry, int oflag) +static struct file *do_open(struct path *path, int oflag)  { -	int ret; -	const struct cred *cred = current_cred(); -  	static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,  						  MAY_READ | MAY_WRITE }; - -	if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { -		ret = -EINVAL; -		goto err; -	} - -	if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) { -		ret = -EACCES; -		goto err; -	} - -	return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred); - -err: -	dput(dentry); -	mntput(ipc_ns->mq_mnt); -	return ERR_PTR(ret); +	int acc; +	if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) +		return ERR_PTR(-EINVAL); +	acc = oflag2acc[oflag & O_ACCMODE]; +	if (inode_permission(path->dentry->d_inode, acc)) +		return ERR_PTR(-EACCES); +	return dentry_open(path, oflag, current_cred());  }  SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,  		struct mq_attr __user *, u_attr)  { -	struct dentry *dentry; +	struct path path;  	struct file *filp;  	char *name;  	struct mq_attr attr;  	int fd, error;  	struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; +	struct dentry *root = ipc_ns->mq_mnt->mnt_root;  	if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))  		return -EFAULT; @@ -822,52 +802,49 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,  	if (fd < 0)  		goto out_putname; -	mutex_lock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); -	dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name)); -	if (IS_ERR(dentry)) { -		error = PTR_ERR(dentry); +	error = 0; +	mutex_lock(&root->d_inode->i_mutex); +	path.dentry = lookup_one_len(name, root, strlen(name)); +	if (IS_ERR(path.dentry)) { +		error = PTR_ERR(path.dentry);  		goto out_putfd;  	} -	mntget(ipc_ns->mq_mnt); +	path.mnt = mntget(ipc_ns->mq_mnt);  	if (oflag & O_CREAT) { -		if (dentry->d_inode) {	/* entry already exists */ -			audit_inode(name, dentry); +		if (path.dentry->d_inode) {	/* entry already exists */ +			audit_inode(name, path.dentry);  			if (oflag & O_EXCL) {  				error = -EEXIST;  				goto out;  			} -			filp = do_open(ipc_ns, dentry, oflag); +			filp = do_open(&path, oflag);  		} else { -			filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root, -						dentry, oflag, mode, +			filp = do_create(ipc_ns, root->d_inode, +						&path, oflag, mode,  						u_attr ? &attr : NULL);  		}  	} else { -		if (!dentry->d_inode) { +		if (!path.dentry->d_inode) {  			error = -ENOENT;  			goto out;  		} -		audit_inode(name, dentry); -		filp = do_open(ipc_ns, dentry, oflag); +		audit_inode(name, path.dentry); +		filp = do_open(&path, oflag);  	} -	if (IS_ERR(filp)) { +	if (!IS_ERR(filp)) +		fd_install(fd, filp); +	else  		error = PTR_ERR(filp); -		goto out_putfd; -	} - -	fd_install(fd, filp); -	goto out_upsem; -  out: -	dput(dentry); -	mntput(ipc_ns->mq_mnt); +	path_put(&path);  out_putfd: -	put_unused_fd(fd); -	fd = error; -out_upsem: -	mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); +	if (error) { +		put_unused_fd(fd); +		fd = error; +	} +	mutex_unlock(&root->d_inode->i_mutex);  out_putname:  	putname(name);  	return fd; diff --git a/ipc/shm.c b/ipc/shm.c index 41c1285d697a..00faa05cf72a 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -953,7 +953,8 @@ out:   * "raddr" thing points to kernel space, and there has to be a wrapper around   * this.   */ -long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) +long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, +	      unsigned long shmlba)  {  	struct shmid_kernel *shp;  	unsigned long addr; @@ -973,9 +974,9 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)  	if (shmid < 0)  		goto out;  	else if ((addr = (ulong)shmaddr)) { -		if (addr & (SHMLBA-1)) { +		if (addr & (shmlba - 1)) {  			if (shmflg & SHM_RND) -				addr &= ~(SHMLBA-1);	   /* round down */ +				addr &= ~(shmlba - 1);	   /* round down */  			else  #ifndef __ARCH_FORCE_SHMLBA  				if (addr & ~PAGE_MASK) @@ -1107,7 +1108,7 @@ SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg)  	unsigned long ret;  	long err; -	err = do_shmat(shmid, shmaddr, shmflg, &ret); +	err = do_shmat(shmid, shmaddr, shmflg, &ret, SHMLBA);  	if (err)  		return err;  	force_successful_syscall_return(); diff --git a/ipc/syscall.c b/ipc/syscall.c index 1d6f53f6b562..0d1e32ce048e 100644 --- a/ipc/syscall.c +++ b/ipc/syscall.c @@ -73,7 +73,7 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,  		default: {  			unsigned long raddr;  			ret = do_shmat(first, (char __user *)ptr, -				       second, &raddr); +				       second, &raddr, SHMLBA);  			if (ret)  				return ret;  			return put_user(raddr, (unsigned long __user *) third); diff --git a/ipc/util.c b/ipc/util.c index 75261a31d48d..eb07fd356f27 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -804,7 +804,7 @@ out_up:  	return ERR_PTR(err);  } -#ifdef __ARCH_WANT_IPC_PARSE_VERSION +#ifdef CONFIG_ARCH_WANT_IPC_PARSE_VERSION  /** @@ -826,7 +826,7 @@ int ipc_parse_version (int *cmd)  	}  } -#endif /* __ARCH_WANT_IPC_PARSE_VERSION */ +#endif /* CONFIG_ARCH_WANT_IPC_PARSE_VERSION */  #ifdef CONFIG_PROC_FS  struct ipc_proc_iter { diff --git a/ipc/util.h b/ipc/util.h index 6f5c20bedaab..850ef3e962cb 100644 --- a/ipc/util.h +++ b/ipc/util.h @@ -130,7 +130,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,  				      struct ipc_ids *ids, int id, int cmd,  				      struct ipc64_perm *perm, int extra_perm); -#ifndef __ARCH_WANT_IPC_PARSE_VERSION +#ifndef CONFIG_ARCH_WANT_IPC_PARSE_VERSION    /* On IA-64, we always use the "64-bit version" of the IPC structures.  */   # define ipc_parse_version(cmd)	IPC_64  #else  | 
