diff options
Diffstat (limited to 'ipc/msg.c')
| -rw-r--r-- | ipc/msg.c | 39 | 
1 files changed, 24 insertions, 15 deletions
diff --git a/ipc/msg.c b/ipc/msg.c index 3b6545302598..883642cf2b27 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -38,6 +38,7 @@  #include <linux/rwsem.h>  #include <linux/nsproxy.h>  #include <linux/ipc_namespace.h> +#include <linux/rhashtable.h>  #include <asm/current.h>  #include <linux/uaccess.h> @@ -162,7 +163,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)  	/* ipc_addid() locks msq upon success. */  	retval = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni);  	if (retval < 0) { -		call_rcu(&msq->q_perm.rcu, msg_rcu_free); +		ipc_rcu_putref(&msq->q_perm, msg_rcu_free);  		return retval;  	} @@ -385,7 +386,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,  	down_write(&msg_ids(ns).rwsem);  	rcu_read_lock(); -	ipcp = ipcctl_pre_down_nolock(ns, &msg_ids(ns), msqid, cmd, +	ipcp = ipcctl_obtain_check(ns, &msg_ids(ns), msqid, cmd,  				      &msqid64->msg_perm, msqid64->msg_qbytes);  	if (IS_ERR(ipcp)) {  		err = PTR_ERR(ipcp); @@ -455,7 +456,7 @@ static int msgctl_info(struct ipc_namespace *ns, int msqid,  			 int cmd, struct msginfo *msginfo)  {  	int err; -	int max_id; +	int max_idx;  	/*  	 * We must not return kernel stack data. @@ -482,16 +483,15 @@ static int msgctl_info(struct ipc_namespace *ns, int msqid,  		msginfo->msgpool = MSGPOOL;  		msginfo->msgtql = MSGTQL;  	} -	max_id = ipc_get_maxid(&msg_ids(ns)); +	max_idx = ipc_get_maxidx(&msg_ids(ns));  	up_read(&msg_ids(ns).rwsem); -	return (max_id < 0) ? 0 : max_id; +	return (max_idx < 0) ? 0 : max_idx;  }  static int msgctl_stat(struct ipc_namespace *ns, int msqid,  			 int cmd, struct msqid64_ds *p)  {  	struct msg_queue *msq; -	int id = 0;  	int err;  	memset(p, 0, sizeof(*p)); @@ -503,7 +503,6 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,  			err = PTR_ERR(msq);  			goto out_unlock;  		} -		id = msq->q_perm.id;  	} else { /* IPC_STAT */  		msq = msq_obtain_object_check(ns, msqid);  		if (IS_ERR(msq)) { @@ -548,10 +547,21 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,  	p->msg_lspid  = pid_vnr(msq->q_lspid);  	p->msg_lrpid  = pid_vnr(msq->q_lrpid); -	ipc_unlock_object(&msq->q_perm); -	rcu_read_unlock(); -	return id; +	if (cmd == IPC_STAT) { +		/* +		 * As defined in SUS: +		 * Return 0 on success +		 */ +		err = 0; +	} else { +		/* +		 * MSG_STAT and MSG_STAT_ANY (both Linux specific) +		 * Return the full id, including the sequence number +		 */ +		err = msq->q_perm.id; +	} +	ipc_unlock_object(&msq->q_perm);  out_unlock:  	rcu_read_unlock();  	return err; @@ -1228,7 +1238,7 @@ COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,  }  #endif -int msg_init_ns(struct ipc_namespace *ns) +void msg_init_ns(struct ipc_namespace *ns)  {  	ns->msg_ctlmax = MSGMAX;  	ns->msg_ctlmnb = MSGMNB; @@ -1236,7 +1246,7 @@ int msg_init_ns(struct ipc_namespace *ns)  	atomic_set(&ns->msg_bytes, 0);  	atomic_set(&ns->msg_hdrs, 0); -	return ipc_init_ids(&ns->ids[IPC_MSG_IDS]); +	ipc_init_ids(&ns->ids[IPC_MSG_IDS]);  }  #ifdef CONFIG_IPC_NS @@ -1277,12 +1287,11 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it)  }  #endif -int __init msg_init(void) +void __init msg_init(void)  { -	const int err = msg_init_ns(&init_ipc_ns); +	msg_init_ns(&init_ipc_ns);  	ipc_init_proc_interface("sysvipc/msg",  				"       key      msqid perms      cbytes       qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n",  				IPC_MSG_IDS, sysvipc_msg_proc_show); -	return err;  }  |