Skip to content

Commit 39a4940

Browse files
committed
ipc/msg: Fix msgctl(..., IPC_STAT, ...) between pid namespaces
Today msg_lspid and msg_lrpid are remembered in the pid namespace of the creator and the processes that last send or received a sysvipc message. If you have processes in multiple pid namespaces that is just wrong. The process ids reported will not make the least bit of sense. This fix is slightly more susceptible to a performance problem than the related fix for System V shared memory. By definition the pids are updated by msgsnd and msgrcv, the fast path of System V message queues. The only concern over the previous implementation is the incrementing and decrementing of the pid reference count. As that is the only difference and multiple updates by of the task_tgid by threads in the same process have been shown in af_unix sockets to create a cache line ping-pong between cpus of the same processor. In this case I don't expect cache lines holding pid reference counts to ping pong between cpus. As senders and receivers update different pids there is a natural separation there. Further if multiple threads of the same process either send or receive messages the pid will be updated to the same value and ipc_update_pid will avoid the reference count update. Which means in the common case I expect msg_lspid and msg_lrpid to remain constant, and reference counts not to be updated when messages are sent. In rare cases it may be possible to trigger the issue which was observed for af_unix sockets, but it will require multiple processes with multiple threads to be either sending or receiving messages. It just does not feel likely that anyone would do that in practice. This change updates msgctl(..., IPC_STAT, ...) to return msg_lspid and msg_lrpid in the pid namespace of the process calling stat. This change also updates cat /proc/sysvipc/msg to return print msg_lspid and msg_lrpid in the pid namespace of the process that opened the proc file. Fixes: b488893 ("pid namespaces: changes to show virtual ids to user") Reviewed-by: Nagarathnam Muthusamy <[email protected]> Signed-off-by: "Eric W. Biederman" <[email protected]>
1 parent 98f929b commit 39a4940

File tree

1 file changed

+13
-10
lines changed

1 file changed

+13
-10
lines changed

ipc/msg.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ struct msg_queue {
5252
unsigned long q_cbytes; /* current number of bytes on queue */
5353
unsigned long q_qnum; /* number of messages in queue */
5454
unsigned long q_qbytes; /* max number of bytes on queue */
55-
pid_t q_lspid; /* pid of last msgsnd */
56-
pid_t q_lrpid; /* last receive pid */
55+
struct pid *q_lspid; /* pid of last msgsnd */
56+
struct pid *q_lrpid; /* last receive pid */
5757

5858
struct list_head q_messages;
5959
struct list_head q_receivers;
@@ -154,7 +154,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
154154
msq->q_ctime = ktime_get_real_seconds();
155155
msq->q_cbytes = msq->q_qnum = 0;
156156
msq->q_qbytes = ns->msg_ctlmnb;
157-
msq->q_lspid = msq->q_lrpid = 0;
157+
msq->q_lspid = msq->q_lrpid = NULL;
158158
INIT_LIST_HEAD(&msq->q_messages);
159159
INIT_LIST_HEAD(&msq->q_receivers);
160160
INIT_LIST_HEAD(&msq->q_senders);
@@ -267,6 +267,8 @@ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
267267
free_msg(msg);
268268
}
269269
atomic_sub(msq->q_cbytes, &ns->msg_bytes);
270+
ipc_update_pid(&msq->q_lspid, NULL);
271+
ipc_update_pid(&msq->q_lrpid, NULL);
270272
ipc_rcu_putref(&msq->q_perm, msg_rcu_free);
271273
}
272274

@@ -536,8 +538,8 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,
536538
p->msg_cbytes = msq->q_cbytes;
537539
p->msg_qnum = msq->q_qnum;
538540
p->msg_qbytes = msq->q_qbytes;
539-
p->msg_lspid = msq->q_lspid;
540-
p->msg_lrpid = msq->q_lrpid;
541+
p->msg_lspid = pid_vnr(msq->q_lspid);
542+
p->msg_lrpid = pid_vnr(msq->q_lrpid);
541543

542544
ipc_unlock_object(&msq->q_perm);
543545
rcu_read_unlock();
@@ -741,7 +743,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg,
741743
wake_q_add(wake_q, msr->r_tsk);
742744
WRITE_ONCE(msr->r_msg, ERR_PTR(-E2BIG));
743745
} else {
744-
msq->q_lrpid = task_pid_vnr(msr->r_tsk);
746+
ipc_update_pid(&msq->q_lrpid, task_pid(msr->r_tsk));
745747
msq->q_rtime = get_seconds();
746748

747749
wake_q_add(wake_q, msr->r_tsk);
@@ -842,7 +844,7 @@ static long do_msgsnd(int msqid, long mtype, void __user *mtext,
842844

843845
}
844846

845-
msq->q_lspid = task_tgid_vnr(current);
847+
ipc_update_pid(&msq->q_lspid, task_tgid(current));
846848
msq->q_stime = get_seconds();
847849

848850
if (!pipelined_send(msq, msg, &wake_q)) {
@@ -1060,7 +1062,7 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in
10601062
list_del(&msg->m_list);
10611063
msq->q_qnum--;
10621064
msq->q_rtime = get_seconds();
1063-
msq->q_lrpid = task_tgid_vnr(current);
1065+
ipc_update_pid(&msq->q_lrpid, task_tgid(current));
10641066
msq->q_cbytes -= msg->m_ts;
10651067
atomic_sub(msg->m_ts, &ns->msg_bytes);
10661068
atomic_dec(&ns->msg_hdrs);
@@ -1202,6 +1204,7 @@ void msg_exit_ns(struct ipc_namespace *ns)
12021204
#ifdef CONFIG_PROC_FS
12031205
static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
12041206
{
1207+
struct pid_namespace *pid_ns = ipc_seq_pid_ns(s);
12051208
struct user_namespace *user_ns = seq_user_ns(s);
12061209
struct kern_ipc_perm *ipcp = it;
12071210
struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);
@@ -1213,8 +1216,8 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
12131216
msq->q_perm.mode,
12141217
msq->q_cbytes,
12151218
msq->q_qnum,
1216-
msq->q_lspid,
1217-
msq->q_lrpid,
1219+
pid_nr_ns(msq->q_lspid, pid_ns),
1220+
pid_nr_ns(msq->q_lrpid, pid_ns),
12181221
from_kuid_munged(user_ns, msq->q_perm.uid),
12191222
from_kgid_munged(user_ns, msq->q_perm.gid),
12201223
from_kuid_munged(user_ns, msq->q_perm.cuid),

0 commit comments

Comments
 (0)