diff options
Diffstat (limited to 'ipc/msg.c')
-rw-r--r-- | ipc/msg.c | 62 |
1 files changed, 36 insertions, 26 deletions
@@ -43,6 +43,23 @@ | |||
43 | #include <linux/uaccess.h> | 43 | #include <linux/uaccess.h> |
44 | #include "util.h" | 44 | #include "util.h" |
45 | 45 | ||
46 | /* one msq_queue structure for each present queue on the system */ | ||
47 | struct msg_queue { | ||
48 | struct kern_ipc_perm q_perm; | ||
49 | time64_t q_stime; /* last msgsnd time */ | ||
50 | time64_t q_rtime; /* last msgrcv time */ | ||
51 | time64_t q_ctime; /* last change time */ | ||
52 | unsigned long q_cbytes; /* current number of bytes on queue */ | ||
53 | unsigned long q_qnum; /* number of messages in queue */ | ||
54 | unsigned long q_qbytes; /* max number of bytes on queue */ | ||
55 | struct pid *q_lspid; /* pid of last msgsnd */ | ||
56 | struct pid *q_lrpid; /* last receive pid */ | ||
57 | |||
58 | struct list_head q_messages; | ||
59 | struct list_head q_receivers; | ||
60 | struct list_head q_senders; | ||
61 | } __randomize_layout; | ||
62 | |||
46 | /* one msg_receiver structure for each sleeping receiver */ | 63 | /* one msg_receiver structure for each sleeping receiver */ |
47 | struct msg_receiver { | 64 | struct msg_receiver { |
48 | struct list_head r_list; | 65 | struct list_head r_list; |
@@ -101,7 +118,7 @@ static void msg_rcu_free(struct rcu_head *head) | |||
101 | struct kern_ipc_perm *p = container_of(head, struct kern_ipc_perm, rcu); | 118 | struct kern_ipc_perm *p = container_of(head, struct kern_ipc_perm, rcu); |
102 | struct msg_queue *msq = container_of(p, struct msg_queue, q_perm); | 119 | struct msg_queue *msq = container_of(p, struct msg_queue, q_perm); |
103 | 120 | ||
104 | security_msg_queue_free(msq); | 121 | security_msg_queue_free(&msq->q_perm); |
105 | kvfree(msq); | 122 | kvfree(msq); |
106 | } | 123 | } |
107 | 124 | ||
@@ -127,7 +144,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params) | |||
127 | msq->q_perm.key = key; | 144 | msq->q_perm.key = key; |
128 | 145 | ||
129 | msq->q_perm.security = NULL; | 146 | msq->q_perm.security = NULL; |
130 | retval = security_msg_queue_alloc(msq); | 147 | retval = security_msg_queue_alloc(&msq->q_perm); |
131 | if (retval) { | 148 | if (retval) { |
132 | kvfree(msq); | 149 | kvfree(msq); |
133 | return retval; | 150 | return retval; |
@@ -137,7 +154,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params) | |||
137 | msq->q_ctime = ktime_get_real_seconds(); | 154 | msq->q_ctime = ktime_get_real_seconds(); |
138 | msq->q_cbytes = msq->q_qnum = 0; | 155 | msq->q_cbytes = msq->q_qnum = 0; |
139 | msq->q_qbytes = ns->msg_ctlmnb; | 156 | msq->q_qbytes = ns->msg_ctlmnb; |
140 | msq->q_lspid = msq->q_lrpid = 0; | 157 | msq->q_lspid = msq->q_lrpid = NULL; |
141 | INIT_LIST_HEAD(&msq->q_messages); | 158 | INIT_LIST_HEAD(&msq->q_messages); |
142 | INIT_LIST_HEAD(&msq->q_receivers); | 159 | INIT_LIST_HEAD(&msq->q_receivers); |
143 | INIT_LIST_HEAD(&msq->q_senders); | 160 | INIT_LIST_HEAD(&msq->q_senders); |
@@ -250,25 +267,17 @@ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) | |||
250 | free_msg(msg); | 267 | free_msg(msg); |
251 | } | 268 | } |
252 | atomic_sub(msq->q_cbytes, &ns->msg_bytes); | 269 | atomic_sub(msq->q_cbytes, &ns->msg_bytes); |
270 | ipc_update_pid(&msq->q_lspid, NULL); | ||
271 | ipc_update_pid(&msq->q_lrpid, NULL); | ||
253 | ipc_rcu_putref(&msq->q_perm, msg_rcu_free); | 272 | ipc_rcu_putref(&msq->q_perm, msg_rcu_free); |
254 | } | 273 | } |
255 | 274 | ||
256 | /* | ||
257 | * Called with msg_ids.rwsem and ipcp locked. | ||
258 | */ | ||
259 | static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg) | ||
260 | { | ||
261 | struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm); | ||
262 | |||
263 | return security_msg_queue_associate(msq, msgflg); | ||
264 | } | ||
265 | |||
266 | long ksys_msgget(key_t key, int msgflg) | 275 | long ksys_msgget(key_t key, int msgflg) |
267 | { | 276 | { |
268 | struct ipc_namespace *ns; | 277 | struct ipc_namespace *ns; |
269 | static const struct ipc_ops msg_ops = { | 278 | static const struct ipc_ops msg_ops = { |
270 | .getnew = newque, | 279 | .getnew = newque, |
271 | .associate = msg_security, | 280 | .associate = security_msg_queue_associate, |
272 | }; | 281 | }; |
273 | struct ipc_params msg_params; | 282 | struct ipc_params msg_params; |
274 | 283 | ||
@@ -385,7 +394,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, | |||
385 | 394 | ||
386 | msq = container_of(ipcp, struct msg_queue, q_perm); | 395 | msq = container_of(ipcp, struct msg_queue, q_perm); |
387 | 396 | ||
388 | err = security_msg_queue_msgctl(msq, cmd); | 397 | err = security_msg_queue_msgctl(&msq->q_perm, cmd); |
389 | if (err) | 398 | if (err) |
390 | goto out_unlock1; | 399 | goto out_unlock1; |
391 | 400 | ||
@@ -507,7 +516,7 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid, | |||
507 | if (ipcperms(ns, &msq->q_perm, S_IRUGO)) | 516 | if (ipcperms(ns, &msq->q_perm, S_IRUGO)) |
508 | goto out_unlock; | 517 | goto out_unlock; |
509 | 518 | ||
510 | err = security_msg_queue_msgctl(msq, cmd); | 519 | err = security_msg_queue_msgctl(&msq->q_perm, cmd); |
511 | if (err) | 520 | if (err) |
512 | goto out_unlock; | 521 | goto out_unlock; |
513 | 522 | ||
@@ -526,8 +535,8 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid, | |||
526 | p->msg_cbytes = msq->q_cbytes; | 535 | p->msg_cbytes = msq->q_cbytes; |
527 | p->msg_qnum = msq->q_qnum; | 536 | p->msg_qnum = msq->q_qnum; |
528 | p->msg_qbytes = msq->q_qbytes; | 537 | p->msg_qbytes = msq->q_qbytes; |
529 | p->msg_lspid = msq->q_lspid; | 538 | p->msg_lspid = pid_vnr(msq->q_lspid); |
530 | p->msg_lrpid = msq->q_lrpid; | 539 | p->msg_lrpid = pid_vnr(msq->q_lrpid); |
531 | 540 | ||
532 | ipc_unlock_object(&msq->q_perm); | 541 | ipc_unlock_object(&msq->q_perm); |
533 | rcu_read_unlock(); | 542 | rcu_read_unlock(); |
@@ -733,7 +742,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg, | |||
733 | 742 | ||
734 | list_for_each_entry_safe(msr, t, &msq->q_receivers, r_list) { | 743 | list_for_each_entry_safe(msr, t, &msq->q_receivers, r_list) { |
735 | if (testmsg(msg, msr->r_msgtype, msr->r_mode) && | 744 | if (testmsg(msg, msr->r_msgtype, msr->r_mode) && |
736 | !security_msg_queue_msgrcv(msq, msg, msr->r_tsk, | 745 | !security_msg_queue_msgrcv(&msq->q_perm, msg, msr->r_tsk, |
737 | msr->r_msgtype, msr->r_mode)) { | 746 | msr->r_msgtype, msr->r_mode)) { |
738 | 747 | ||
739 | list_del(&msr->r_list); | 748 | list_del(&msr->r_list); |
@@ -741,7 +750,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg, | |||
741 | wake_q_add(wake_q, msr->r_tsk); | 750 | wake_q_add(wake_q, msr->r_tsk); |
742 | WRITE_ONCE(msr->r_msg, ERR_PTR(-E2BIG)); | 751 | WRITE_ONCE(msr->r_msg, ERR_PTR(-E2BIG)); |
743 | } else { | 752 | } else { |
744 | msq->q_lrpid = task_pid_vnr(msr->r_tsk); | 753 | ipc_update_pid(&msq->q_lrpid, task_pid(msr->r_tsk)); |
745 | msq->q_rtime = get_seconds(); | 754 | msq->q_rtime = get_seconds(); |
746 | 755 | ||
747 | wake_q_add(wake_q, msr->r_tsk); | 756 | wake_q_add(wake_q, msr->r_tsk); |
@@ -799,7 +808,7 @@ static long do_msgsnd(int msqid, long mtype, void __user *mtext, | |||
799 | goto out_unlock0; | 808 | goto out_unlock0; |
800 | } | 809 | } |
801 | 810 | ||
802 | err = security_msg_queue_msgsnd(msq, msg, msgflg); | 811 | err = security_msg_queue_msgsnd(&msq->q_perm, msg, msgflg); |
803 | if (err) | 812 | if (err) |
804 | goto out_unlock0; | 813 | goto out_unlock0; |
805 | 814 | ||
@@ -842,7 +851,7 @@ static long do_msgsnd(int msqid, long mtype, void __user *mtext, | |||
842 | 851 | ||
843 | } | 852 | } |
844 | 853 | ||
845 | msq->q_lspid = task_tgid_vnr(current); | 854 | ipc_update_pid(&msq->q_lspid, task_tgid(current)); |
846 | msq->q_stime = get_seconds(); | 855 | msq->q_stime = get_seconds(); |
847 | 856 | ||
848 | if (!pipelined_send(msq, msg, &wake_q)) { | 857 | if (!pipelined_send(msq, msg, &wake_q)) { |
@@ -987,7 +996,7 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode) | |||
987 | 996 | ||
988 | list_for_each_entry(msg, &msq->q_messages, m_list) { | 997 | list_for_each_entry(msg, &msq->q_messages, m_list) { |
989 | if (testmsg(msg, *msgtyp, mode) && | 998 | if (testmsg(msg, *msgtyp, mode) && |
990 | !security_msg_queue_msgrcv(msq, msg, current, | 999 | !security_msg_queue_msgrcv(&msq->q_perm, msg, current, |
991 | *msgtyp, mode)) { | 1000 | *msgtyp, mode)) { |
992 | if (mode == SEARCH_LESSEQUAL && msg->m_type != 1) { | 1001 | if (mode == SEARCH_LESSEQUAL && msg->m_type != 1) { |
993 | *msgtyp = msg->m_type - 1; | 1002 | *msgtyp = msg->m_type - 1; |
@@ -1072,7 +1081,7 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in | |||
1072 | list_del(&msg->m_list); | 1081 | list_del(&msg->m_list); |
1073 | msq->q_qnum--; | 1082 | msq->q_qnum--; |
1074 | msq->q_rtime = get_seconds(); | 1083 | msq->q_rtime = get_seconds(); |
1075 | msq->q_lrpid = task_tgid_vnr(current); | 1084 | ipc_update_pid(&msq->q_lrpid, task_tgid(current)); |
1076 | msq->q_cbytes -= msg->m_ts; | 1085 | msq->q_cbytes -= msg->m_ts; |
1077 | atomic_sub(msg->m_ts, &ns->msg_bytes); | 1086 | atomic_sub(msg->m_ts, &ns->msg_bytes); |
1078 | atomic_dec(&ns->msg_hdrs); | 1087 | atomic_dec(&ns->msg_hdrs); |
@@ -1227,6 +1236,7 @@ void msg_exit_ns(struct ipc_namespace *ns) | |||
1227 | #ifdef CONFIG_PROC_FS | 1236 | #ifdef CONFIG_PROC_FS |
1228 | static int sysvipc_msg_proc_show(struct seq_file *s, void *it) | 1237 | static int sysvipc_msg_proc_show(struct seq_file *s, void *it) |
1229 | { | 1238 | { |
1239 | struct pid_namespace *pid_ns = ipc_seq_pid_ns(s); | ||
1230 | struct user_namespace *user_ns = seq_user_ns(s); | 1240 | struct user_namespace *user_ns = seq_user_ns(s); |
1231 | struct kern_ipc_perm *ipcp = it; | 1241 | struct kern_ipc_perm *ipcp = it; |
1232 | struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm); | 1242 | struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm); |
@@ -1238,8 +1248,8 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it) | |||
1238 | msq->q_perm.mode, | 1248 | msq->q_perm.mode, |
1239 | msq->q_cbytes, | 1249 | msq->q_cbytes, |
1240 | msq->q_qnum, | 1250 | msq->q_qnum, |
1241 | msq->q_lspid, | 1251 | pid_nr_ns(msq->q_lspid, pid_ns), |
1242 | msq->q_lrpid, | 1252 | pid_nr_ns(msq->q_lrpid, pid_ns), |
1243 | from_kuid_munged(user_ns, msq->q_perm.uid), | 1253 | from_kuid_munged(user_ns, msq->q_perm.uid), |
1244 | from_kgid_munged(user_ns, msq->q_perm.gid), | 1254 | from_kgid_munged(user_ns, msq->q_perm.gid), |
1245 | from_kuid_munged(user_ns, msq->q_perm.cuid), | 1255 | from_kuid_munged(user_ns, msq->q_perm.cuid), |