diff options
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/compat.c | 46 | ||||
-rw-r--r-- | ipc/ipc_sysctl.c | 32 | ||||
-rw-r--r-- | ipc/msg.c | 123 | ||||
-rw-r--r-- | ipc/msgutil.c | 43 | ||||
-rw-r--r-- | ipc/util.c | 16 | ||||
-rw-r--r-- | ipc/util.h | 2 |
6 files changed, 205 insertions, 57 deletions
diff --git a/ipc/compat.c b/ipc/compat.c index ad9518eb26e0..2547f29dcd1b 100644 --- a/ipc/compat.c +++ b/ipc/compat.c | |||
@@ -306,6 +306,20 @@ static long do_compat_semctl(int first, int second, int third, u32 pad) | |||
306 | return err; | 306 | return err; |
307 | } | 307 | } |
308 | 308 | ||
309 | long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) | ||
310 | { | ||
311 | struct compat_msgbuf __user *msgp = dest; | ||
312 | size_t msgsz; | ||
313 | |||
314 | if (put_user(msg->m_type, &msgp->mtype)) | ||
315 | return -EFAULT; | ||
316 | |||
317 | msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz; | ||
318 | if (store_msg(msgp->mtext, msg, msgsz)) | ||
319 | return -EFAULT; | ||
320 | return msgsz; | ||
321 | } | ||
322 | |||
309 | #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC | 323 | #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC |
310 | long compat_sys_semctl(int first, int second, int third, void __user *uptr) | 324 | long compat_sys_semctl(int first, int second, int third, void __user *uptr) |
311 | { | 325 | { |
@@ -337,10 +351,6 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr) | |||
337 | long compat_sys_msgrcv(int first, int second, int msgtyp, int third, | 351 | long compat_sys_msgrcv(int first, int second, int msgtyp, int third, |
338 | int version, void __user *uptr) | 352 | int version, void __user *uptr) |
339 | { | 353 | { |
340 | struct compat_msgbuf __user *up; | ||
341 | long type; | ||
342 | int err; | ||
343 | |||
344 | if (first < 0) | 354 | if (first < 0) |
345 | return -EINVAL; | 355 | return -EINVAL; |
346 | if (second < 0) | 356 | if (second < 0) |
@@ -348,23 +358,15 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third, | |||
348 | 358 | ||
349 | if (!version) { | 359 | if (!version) { |
350 | struct compat_ipc_kludge ipck; | 360 | struct compat_ipc_kludge ipck; |
351 | err = -EINVAL; | ||
352 | if (!uptr) | 361 | if (!uptr) |
353 | goto out; | 362 | return -EINVAL; |
354 | err = -EFAULT; | ||
355 | if (copy_from_user (&ipck, uptr, sizeof(ipck))) | 363 | if (copy_from_user (&ipck, uptr, sizeof(ipck))) |
356 | goto out; | 364 | return -EFAULT; |
357 | uptr = compat_ptr(ipck.msgp); | 365 | uptr = compat_ptr(ipck.msgp); |
358 | msgtyp = ipck.msgtyp; | 366 | msgtyp = ipck.msgtyp; |
359 | } | 367 | } |
360 | up = uptr; | 368 | return do_msgrcv(first, uptr, second, msgtyp, third, |
361 | err = do_msgrcv(first, &type, up->mtext, second, msgtyp, third); | 369 | compat_do_msg_fill); |
362 | if (err < 0) | ||
363 | goto out; | ||
364 | if (put_user(type, &up->mtype)) | ||
365 | err = -EFAULT; | ||
366 | out: | ||
367 | return err; | ||
368 | } | 370 | } |
369 | #else | 371 | #else |
370 | long compat_sys_semctl(int semid, int semnum, int cmd, int arg) | 372 | long compat_sys_semctl(int semid, int semnum, int cmd, int arg) |
@@ -385,16 +387,8 @@ long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp, | |||
385 | long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp, | 387 | long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp, |
386 | compat_ssize_t msgsz, long msgtyp, int msgflg) | 388 | compat_ssize_t msgsz, long msgtyp, int msgflg) |
387 | { | 389 | { |
388 | long err, mtype; | 390 | return do_msgrcv(msqid, msgp, (ssize_t)msgsz, msgtyp, msgflg, |
389 | 391 | compat_do_msg_fill); | |
390 | err = do_msgrcv(msqid, &mtype, msgp->mtext, (ssize_t)msgsz, msgtyp, msgflg); | ||
391 | if (err < 0) | ||
392 | goto out; | ||
393 | |||
394 | if (put_user(mtype, &msgp->mtype)) | ||
395 | err = -EFAULT; | ||
396 | out: | ||
397 | return err; | ||
398 | } | 392 | } |
399 | #endif | 393 | #endif |
400 | 394 | ||
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index 00fba2bab87d..130dfece27ac 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c | |||
@@ -158,6 +158,9 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, | |||
158 | 158 | ||
159 | static int zero; | 159 | static int zero; |
160 | static int one = 1; | 160 | static int one = 1; |
161 | #ifdef CONFIG_CHECKPOINT_RESTORE | ||
162 | static int int_max = INT_MAX; | ||
163 | #endif | ||
161 | 164 | ||
162 | static struct ctl_table ipc_kern_table[] = { | 165 | static struct ctl_table ipc_kern_table[] = { |
163 | { | 166 | { |
@@ -227,6 +230,35 @@ static struct ctl_table ipc_kern_table[] = { | |||
227 | .extra1 = &zero, | 230 | .extra1 = &zero, |
228 | .extra2 = &one, | 231 | .extra2 = &one, |
229 | }, | 232 | }, |
233 | #ifdef CONFIG_CHECKPOINT_RESTORE | ||
234 | { | ||
235 | .procname = "sem_next_id", | ||
236 | .data = &init_ipc_ns.ids[IPC_SEM_IDS].next_id, | ||
237 | .maxlen = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id), | ||
238 | .mode = 0644, | ||
239 | .proc_handler = proc_ipc_dointvec_minmax, | ||
240 | .extra1 = &zero, | ||
241 | .extra2 = &int_max, | ||
242 | }, | ||
243 | { | ||
244 | .procname = "msg_next_id", | ||
245 | .data = &init_ipc_ns.ids[IPC_MSG_IDS].next_id, | ||
246 | .maxlen = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id), | ||
247 | .mode = 0644, | ||
248 | .proc_handler = proc_ipc_dointvec_minmax, | ||
249 | .extra1 = &zero, | ||
250 | .extra2 = &int_max, | ||
251 | }, | ||
252 | { | ||
253 | .procname = "shm_next_id", | ||
254 | .data = &init_ipc_ns.ids[IPC_SHM_IDS].next_id, | ||
255 | .maxlen = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id), | ||
256 | .mode = 0644, | ||
257 | .proc_handler = proc_ipc_dointvec_minmax, | ||
258 | .extra1 = &zero, | ||
259 | .extra2 = &int_max, | ||
260 | }, | ||
261 | #endif | ||
230 | {} | 262 | {} |
231 | }; | 263 | }; |
232 | 264 | ||
@@ -755,26 +755,91 @@ static inline int convert_mode(long *msgtyp, int msgflg) | |||
755 | return SEARCH_EQUAL; | 755 | return SEARCH_EQUAL; |
756 | } | 756 | } |
757 | 757 | ||
758 | long do_msgrcv(int msqid, long *pmtype, void __user *mtext, | 758 | static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) |
759 | size_t msgsz, long msgtyp, int msgflg) | 759 | { |
760 | struct msgbuf __user *msgp = dest; | ||
761 | size_t msgsz; | ||
762 | |||
763 | if (put_user(msg->m_type, &msgp->mtype)) | ||
764 | return -EFAULT; | ||
765 | |||
766 | msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz; | ||
767 | if (store_msg(msgp->mtext, msg, msgsz)) | ||
768 | return -EFAULT; | ||
769 | return msgsz; | ||
770 | } | ||
771 | |||
772 | #ifdef CONFIG_CHECKPOINT_RESTORE | ||
773 | /* | ||
774 | * This function creates new kernel message structure, large enough to store | ||
775 | * bufsz message bytes. | ||
776 | */ | ||
777 | static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz, | ||
778 | int msgflg, long *msgtyp, | ||
779 | unsigned long *copy_number) | ||
780 | { | ||
781 | struct msg_msg *copy; | ||
782 | |||
783 | *copy_number = *msgtyp; | ||
784 | *msgtyp = 0; | ||
785 | /* | ||
786 | * Create dummy message to copy real message to. | ||
787 | */ | ||
788 | copy = load_msg(buf, bufsz); | ||
789 | if (!IS_ERR(copy)) | ||
790 | copy->m_ts = bufsz; | ||
791 | return copy; | ||
792 | } | ||
793 | |||
794 | static inline void free_copy(struct msg_msg *copy) | ||
795 | { | ||
796 | if (copy) | ||
797 | free_msg(copy); | ||
798 | } | ||
799 | #else | ||
800 | static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz, | ||
801 | int msgflg, long *msgtyp, | ||
802 | unsigned long *copy_number) | ||
803 | { | ||
804 | return ERR_PTR(-ENOSYS); | ||
805 | } | ||
806 | |||
807 | static inline void free_copy(struct msg_msg *copy) | ||
808 | { | ||
809 | } | ||
810 | #endif | ||
811 | |||
812 | long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, | ||
813 | int msgflg, | ||
814 | long (*msg_handler)(void __user *, struct msg_msg *, size_t)) | ||
760 | { | 815 | { |
761 | struct msg_queue *msq; | 816 | struct msg_queue *msq; |
762 | struct msg_msg *msg; | 817 | struct msg_msg *msg; |
763 | int mode; | 818 | int mode; |
764 | struct ipc_namespace *ns; | 819 | struct ipc_namespace *ns; |
820 | struct msg_msg *copy = NULL; | ||
821 | unsigned long copy_number = 0; | ||
765 | 822 | ||
766 | if (msqid < 0 || (long) msgsz < 0) | 823 | if (msqid < 0 || (long) bufsz < 0) |
767 | return -EINVAL; | 824 | return -EINVAL; |
825 | if (msgflg & MSG_COPY) { | ||
826 | copy = prepare_copy(buf, bufsz, msgflg, &msgtyp, ©_number); | ||
827 | if (IS_ERR(copy)) | ||
828 | return PTR_ERR(copy); | ||
829 | } | ||
768 | mode = convert_mode(&msgtyp, msgflg); | 830 | mode = convert_mode(&msgtyp, msgflg); |
769 | ns = current->nsproxy->ipc_ns; | 831 | ns = current->nsproxy->ipc_ns; |
770 | 832 | ||
771 | msq = msg_lock_check(ns, msqid); | 833 | msq = msg_lock_check(ns, msqid); |
772 | if (IS_ERR(msq)) | 834 | if (IS_ERR(msq)) { |
835 | free_copy(copy); | ||
773 | return PTR_ERR(msq); | 836 | return PTR_ERR(msq); |
837 | } | ||
774 | 838 | ||
775 | for (;;) { | 839 | for (;;) { |
776 | struct msg_receiver msr_d; | 840 | struct msg_receiver msr_d; |
777 | struct list_head *tmp; | 841 | struct list_head *tmp; |
842 | long msg_counter = 0; | ||
778 | 843 | ||
779 | msg = ERR_PTR(-EACCES); | 844 | msg = ERR_PTR(-EACCES); |
780 | if (ipcperms(ns, &msq->q_perm, S_IRUGO)) | 845 | if (ipcperms(ns, &msq->q_perm, S_IRUGO)) |
@@ -793,12 +858,21 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, | |||
793 | msg = walk_msg; | 858 | msg = walk_msg; |
794 | if (mode == SEARCH_LESSEQUAL && | 859 | if (mode == SEARCH_LESSEQUAL && |
795 | walk_msg->m_type != 1) { | 860 | walk_msg->m_type != 1) { |
796 | msg = walk_msg; | ||
797 | msgtyp = walk_msg->m_type - 1; | 861 | msgtyp = walk_msg->m_type - 1; |
798 | } else { | 862 | } else if (msgflg & MSG_COPY) { |
799 | msg = walk_msg; | 863 | if (copy_number == msg_counter) { |
864 | /* | ||
865 | * Found requested message. | ||
866 | * Copy it. | ||
867 | */ | ||
868 | msg = copy_msg(msg, copy); | ||
869 | if (IS_ERR(msg)) | ||
870 | goto out_unlock; | ||
871 | break; | ||
872 | } | ||
873 | } else | ||
800 | break; | 874 | break; |
801 | } | 875 | msg_counter++; |
802 | } | 876 | } |
803 | tmp = tmp->next; | 877 | tmp = tmp->next; |
804 | } | 878 | } |
@@ -807,10 +881,16 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, | |||
807 | * Found a suitable message. | 881 | * Found a suitable message. |
808 | * Unlink it from the queue. | 882 | * Unlink it from the queue. |
809 | */ | 883 | */ |
810 | if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) { | 884 | if ((bufsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) { |
811 | msg = ERR_PTR(-E2BIG); | 885 | msg = ERR_PTR(-E2BIG); |
812 | goto out_unlock; | 886 | goto out_unlock; |
813 | } | 887 | } |
888 | /* | ||
889 | * If we are copying, then do not unlink message and do | ||
890 | * not update queue parameters. | ||
891 | */ | ||
892 | if (msgflg & MSG_COPY) | ||
893 | goto out_unlock; | ||
814 | list_del(&msg->m_list); | 894 | list_del(&msg->m_list); |
815 | msq->q_qnum--; | 895 | msq->q_qnum--; |
816 | msq->q_rtime = get_seconds(); | 896 | msq->q_rtime = get_seconds(); |
@@ -834,7 +914,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, | |||
834 | if (msgflg & MSG_NOERROR) | 914 | if (msgflg & MSG_NOERROR) |
835 | msr_d.r_maxsize = INT_MAX; | 915 | msr_d.r_maxsize = INT_MAX; |
836 | else | 916 | else |
837 | msr_d.r_maxsize = msgsz; | 917 | msr_d.r_maxsize = bufsz; |
838 | msr_d.r_msg = ERR_PTR(-EAGAIN); | 918 | msr_d.r_msg = ERR_PTR(-EAGAIN); |
839 | current->state = TASK_INTERRUPTIBLE; | 919 | current->state = TASK_INTERRUPTIBLE; |
840 | msg_unlock(msq); | 920 | msg_unlock(msq); |
@@ -894,32 +974,21 @@ out_unlock: | |||
894 | break; | 974 | break; |
895 | } | 975 | } |
896 | } | 976 | } |
897 | if (IS_ERR(msg)) | 977 | if (IS_ERR(msg)) { |
978 | free_copy(copy); | ||
898 | return PTR_ERR(msg); | 979 | return PTR_ERR(msg); |
980 | } | ||
899 | 981 | ||
900 | msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz; | 982 | bufsz = msg_handler(buf, msg, bufsz); |
901 | *pmtype = msg->m_type; | ||
902 | if (store_msg(mtext, msg, msgsz)) | ||
903 | msgsz = -EFAULT; | ||
904 | |||
905 | free_msg(msg); | 983 | free_msg(msg); |
906 | 984 | ||
907 | return msgsz; | 985 | return bufsz; |
908 | } | 986 | } |
909 | 987 | ||
910 | SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, | 988 | SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, |
911 | long, msgtyp, int, msgflg) | 989 | long, msgtyp, int, msgflg) |
912 | { | 990 | { |
913 | long err, mtype; | 991 | return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill); |
914 | |||
915 | err = do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg); | ||
916 | if (err < 0) | ||
917 | goto out; | ||
918 | |||
919 | if (put_user(mtype, &msgp->mtype)) | ||
920 | err = -EFAULT; | ||
921 | out: | ||
922 | return err; | ||
923 | } | 992 | } |
924 | 993 | ||
925 | #ifdef CONFIG_PROC_FS | 994 | #ifdef CONFIG_PROC_FS |
diff --git a/ipc/msgutil.c b/ipc/msgutil.c index 6471f1bdae96..ebfcbfa8b7f2 100644 --- a/ipc/msgutil.c +++ b/ipc/msgutil.c | |||
@@ -102,7 +102,50 @@ out_err: | |||
102 | free_msg(msg); | 102 | free_msg(msg); |
103 | return ERR_PTR(err); | 103 | return ERR_PTR(err); |
104 | } | 104 | } |
105 | #ifdef CONFIG_CHECKPOINT_RESTORE | ||
106 | struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst) | ||
107 | { | ||
108 | struct msg_msgseg *dst_pseg, *src_pseg; | ||
109 | int len = src->m_ts; | ||
110 | int alen; | ||
111 | |||
112 | BUG_ON(dst == NULL); | ||
113 | if (src->m_ts > dst->m_ts) | ||
114 | return ERR_PTR(-EINVAL); | ||
105 | 115 | ||
116 | alen = len; | ||
117 | if (alen > DATALEN_MSG) | ||
118 | alen = DATALEN_MSG; | ||
119 | |||
120 | dst->next = NULL; | ||
121 | dst->security = NULL; | ||
122 | |||
123 | memcpy(dst + 1, src + 1, alen); | ||
124 | |||
125 | len -= alen; | ||
126 | dst_pseg = dst->next; | ||
127 | src_pseg = src->next; | ||
128 | while (len > 0) { | ||
129 | alen = len; | ||
130 | if (alen > DATALEN_SEG) | ||
131 | alen = DATALEN_SEG; | ||
132 | memcpy(dst_pseg + 1, src_pseg + 1, alen); | ||
133 | dst_pseg = dst_pseg->next; | ||
134 | len -= alen; | ||
135 | src_pseg = src_pseg->next; | ||
136 | } | ||
137 | |||
138 | dst->m_type = src->m_type; | ||
139 | dst->m_ts = src->m_ts; | ||
140 | |||
141 | return dst; | ||
142 | } | ||
143 | #else | ||
144 | struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst) | ||
145 | { | ||
146 | return ERR_PTR(-ENOSYS); | ||
147 | } | ||
148 | #endif | ||
106 | int store_msg(void __user *dest, struct msg_msg *msg, int len) | 149 | int store_msg(void __user *dest, struct msg_msg *msg, int len) |
107 | { | 150 | { |
108 | int alen; | 151 | int alen; |
diff --git a/ipc/util.c b/ipc/util.c index 72fd0785ac94..74e1d9c7a98a 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -122,6 +122,7 @@ void ipc_init_ids(struct ipc_ids *ids) | |||
122 | 122 | ||
123 | ids->in_use = 0; | 123 | ids->in_use = 0; |
124 | ids->seq = 0; | 124 | ids->seq = 0; |
125 | ids->next_id = -1; | ||
125 | { | 126 | { |
126 | int seq_limit = INT_MAX/SEQ_MULTIPLIER; | 127 | int seq_limit = INT_MAX/SEQ_MULTIPLIER; |
127 | if (seq_limit > USHRT_MAX) | 128 | if (seq_limit > USHRT_MAX) |
@@ -252,6 +253,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | |||
252 | kuid_t euid; | 253 | kuid_t euid; |
253 | kgid_t egid; | 254 | kgid_t egid; |
254 | int id, err; | 255 | int id, err; |
256 | int next_id = ids->next_id; | ||
255 | 257 | ||
256 | if (size > IPCMNI) | 258 | if (size > IPCMNI) |
257 | size = IPCMNI; | 259 | size = IPCMNI; |
@@ -264,7 +266,8 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | |||
264 | rcu_read_lock(); | 266 | rcu_read_lock(); |
265 | spin_lock(&new->lock); | 267 | spin_lock(&new->lock); |
266 | 268 | ||
267 | err = idr_get_new(&ids->ipcs_idr, new, &id); | 269 | err = idr_get_new_above(&ids->ipcs_idr, new, |
270 | (next_id < 0) ? 0 : ipcid_to_idx(next_id), &id); | ||
268 | if (err) { | 271 | if (err) { |
269 | spin_unlock(&new->lock); | 272 | spin_unlock(&new->lock); |
270 | rcu_read_unlock(); | 273 | rcu_read_unlock(); |
@@ -277,9 +280,14 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | |||
277 | new->cuid = new->uid = euid; | 280 | new->cuid = new->uid = euid; |
278 | new->gid = new->cgid = egid; | 281 | new->gid = new->cgid = egid; |
279 | 282 | ||
280 | new->seq = ids->seq++; | 283 | if (next_id < 0) { |
281 | if(ids->seq > ids->seq_max) | 284 | new->seq = ids->seq++; |
282 | ids->seq = 0; | 285 | if (ids->seq > ids->seq_max) |
286 | ids->seq = 0; | ||
287 | } else { | ||
288 | new->seq = ipcid_to_seqx(next_id); | ||
289 | ids->next_id = -1; | ||
290 | } | ||
283 | 291 | ||
284 | new->id = ipc_buildid(id, new->seq); | 292 | new->id = ipc_buildid(id, new->seq); |
285 | return id; | 293 | return id; |
diff --git a/ipc/util.h b/ipc/util.h index c8fe2f7631e9..eeb79a1fbd83 100644 --- a/ipc/util.h +++ b/ipc/util.h | |||
@@ -92,6 +92,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header, | |||
92 | #define IPC_SHM_IDS 2 | 92 | #define IPC_SHM_IDS 2 |
93 | 93 | ||
94 | #define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER) | 94 | #define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER) |
95 | #define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER) | ||
95 | 96 | ||
96 | /* must be called with ids->rw_mutex acquired for writing */ | 97 | /* must be called with ids->rw_mutex acquired for writing */ |
97 | int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int); | 98 | int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int); |
@@ -139,6 +140,7 @@ int ipc_parse_version (int *cmd); | |||
139 | 140 | ||
140 | extern void free_msg(struct msg_msg *msg); | 141 | extern void free_msg(struct msg_msg *msg); |
141 | extern struct msg_msg *load_msg(const void __user *src, int len); | 142 | extern struct msg_msg *load_msg(const void __user *src, int len); |
143 | extern struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst); | ||
142 | extern int store_msg(void __user *dest, struct msg_msg *msg, int len); | 144 | extern int store_msg(void __user *dest, struct msg_msg *msg, int len); |
143 | 145 | ||
144 | extern void recompute_msgmni(struct ipc_namespace *); | 146 | extern void recompute_msgmni(struct ipc_namespace *); |