1 // SPDX-License-Identifier: GPL-2.0
4 * Copyright (C) 1992 Krishna Balasubramanian
6 * Sep 1997 - Call suser() last after "normal" permission checks so we
7 * get BSD style process accounting right.
8 * Occurs in several places in the IPC code.
9 * Chris Evans, <chris@ferret.lmh.ox.ac.uk>
10 * Nov 1999 - ipc helper functions, unified SMP locking
11 * Manfred Spraul <manfred@colorfullife.com>
12 * Oct 2002 - One lock per IPC id. RCU ipc_free for lock-free grow_ary().
13 * Mingming Cao <cmm@us.ibm.com>
14 * Mar 2006 - support for audit of ipc object properties
15 * Dustin Kirkland <dustin.kirkland@us.ibm.com>
16 * Jun 2006 - namespaces ssupport
18 * Pavel Emelianov <xemul@openvz.org>
20 * General sysv ipc locking scheme:
22 * obtain the ipc object (kern_ipc_perm) by looking up the id in an idr
24 * - perform initial checks (capabilities, auditing and permission,
26 * - perform read-only operations, such as INFO command, that
27 * do not demand atomicity
28 * acquire the ipc lock (kern_ipc_perm.lock) through
30 * - perform read-only operations that demand atomicity,
31 * such as STAT command.
32 * - perform data updates, such as SET, RMID commands and
33 * mechanism-specific operations (semop/semtimedop,
34 * msgsnd/msgrcv, shmat/shmdt).
35 * drop the ipc lock, through ipc_unlock_object().
38 * The ids->rwsem must be taken when:
39 * - creating, removing and iterating the existing entries in ipc
41 * - iterating through files under /proc/sysvipc/
43 * Note that sems have a special fast path that avoids kern_ipc_perm.lock -
48 #include <linux/shm.h>
49 #include <linux/init.h>
50 #include <linux/msg.h>
51 #include <linux/vmalloc.h>
52 #include <linux/slab.h>
53 #include <linux/notifier.h>
54 #include <linux/capability.h>
55 #include <linux/highuid.h>
56 #include <linux/security.h>
57 #include <linux/rcupdate.h>
58 #include <linux/workqueue.h>
59 #include <linux/seq_file.h>
60 #include <linux/proc_fs.h>
61 #include <linux/audit.h>
62 #include <linux/nsproxy.h>
63 #include <linux/rwsem.h>
64 #include <linux/memory.h>
65 #include <linux/ipc_namespace.h>
66 #include <linux/rhashtable.h>
67 #include <linux/log2.h>
69 #include <asm/unistd.h>
73 struct ipc_proc_iface
{
77 int (*show
)(struct seq_file
*, void *);
81 * ipc_init - initialise ipc subsystem
83 * The various sysv ipc resources (semaphores, messages and shared
84 * memory) are initialised.
86 * A callback routine is registered into the memory hotplug notifier
87 * chain: since msgmni scales to lowmem this callback routine will be
88 * called upon successful memory add / remove to recompute msmgni.
90 static int __init
ipc_init(void)
92 proc_mkdir("sysvipc", NULL
);
99 device_initcall(ipc_init
);
101 static const struct rhashtable_params ipc_kht_params
= {
102 .head_offset
= offsetof(struct kern_ipc_perm
, khtnode
),
103 .key_offset
= offsetof(struct kern_ipc_perm
, key
),
104 .key_len
= sizeof_field(struct kern_ipc_perm
, key
),
105 .automatic_shrinking
= true,
109 * ipc_init_ids - initialise ipc identifiers
110 * @ids: ipc identifier set
112 * Set up the sequence range to use for the ipc identifier range (limited
113 * below ipc_mni) then initialise the keys hashtable and ids idr.
115 void ipc_init_ids(struct ipc_ids
*ids
)
119 init_rwsem(&ids
->rwsem
);
120 rhashtable_init(&ids
->key_ht
, &ipc_kht_params
);
121 idr_init(&ids
->ipcs_idr
);
124 #ifdef CONFIG_CHECKPOINT_RESTORE
129 #ifdef CONFIG_PROC_FS
130 static const struct proc_ops sysvipc_proc_ops
;
132 * ipc_init_proc_interface - create a proc interface for sysipc types using a seq_file interface.
133 * @path: Path in procfs
134 * @header: Banner to be printed at the beginning of the file.
135 * @ids: ipc id table to iterate.
136 * @show: show routine.
138 void __init
ipc_init_proc_interface(const char *path
, const char *header
,
139 int ids
, int (*show
)(struct seq_file
*, void *))
141 struct proc_dir_entry
*pde
;
142 struct ipc_proc_iface
*iface
;
144 iface
= kmalloc(sizeof(*iface
), GFP_KERNEL
);
148 iface
->header
= header
;
152 pde
= proc_create_data(path
,
153 S_IRUGO
, /* world readable */
154 NULL
, /* parent dir */
163 * ipc_findkey - find a key in an ipc identifier set
164 * @ids: ipc identifier set
167 * Returns the locked pointer to the ipc structure if found or NULL
168 * otherwise. If key is found ipc points to the owning ipc structure
170 * Called with writer ipc_ids.rwsem held.
172 static struct kern_ipc_perm
*ipc_findkey(struct ipc_ids
*ids
, key_t key
)
174 struct kern_ipc_perm
*ipcp
;
176 ipcp
= rhashtable_lookup_fast(&ids
->key_ht
, &key
,
182 ipc_lock_object(ipcp
);
187 * Insert new IPC object into idr tree, and set sequence number and id
188 * in the correct order.
190 * - the sequence number must be set before inserting the object into the idr,
191 * because the sequence number is accessed without a lock.
192 * - the id can/must be set after inserting the object into the idr.
193 * All accesses must be done after getting kern_ipc_perm.lock.
195 * The caller must own kern_ipc_perm.lock.of the new object.
196 * On error, the function returns a (negative) error code.
198 * To conserve sequence number space, especially with extended ipc_mni,
199 * the sequence number is incremented only when the returned ID is less than
202 static inline int ipc_idr_alloc(struct ipc_ids
*ids
, struct kern_ipc_perm
*new)
204 int idx
, next_id
= -1;
206 #ifdef CONFIG_CHECKPOINT_RESTORE
207 next_id
= ids
->next_id
;
212 * As soon as a new object is inserted into the idr,
213 * ipc_obtain_object_idr() or ipc_obtain_object_check() can find it,
214 * and the lockless preparations for ipc operations can start.
215 * This means especially: permission checks, audit calls, allocation
216 * of undo structures, ...
218 * Thus the object must be fully initialized, and if something fails,
219 * then the full tear-down sequence must be followed.
220 * (i.e.: set new->deleted, reduce refcount, call_rcu())
223 if (next_id
< 0) { /* !CHECKPOINT_RESTORE or next_id is unset */
226 max_idx
= max(ids
->in_use
*3/2, ipc_min_cycle
);
227 max_idx
= min(max_idx
, ipc_mni
);
229 /* allocate the idx, with a NULL struct kern_ipc_perm */
230 idx
= idr_alloc_cyclic(&ids
->ipcs_idr
, NULL
, 0, max_idx
,
235 * idx got allocated successfully.
236 * Now calculate the sequence number and set the
239 if (idx
<= ids
->last_idx
) {
241 if (ids
->seq
>= ipcid_seq_max())
247 /* no need for smp_wmb(), this is done
248 * inside idr_replace, as part of
251 idr_replace(&ids
->ipcs_idr
, new, idx
);
254 new->seq
= ipcid_to_seqx(next_id
);
255 idx
= idr_alloc(&ids
->ipcs_idr
, new, ipcid_to_idx(next_id
),
259 new->id
= (new->seq
<< ipcmni_seq_shift()) + idx
;
264 * ipc_addid - add an ipc identifier
265 * @ids: ipc identifier set
266 * @new: new ipc permission set
267 * @limit: limit for the number of used ids
269 * Add an entry 'new' to the ipc ids idr. The permissions object is
270 * initialised and the first free entry is set up and the index assigned
271 * is returned. The 'new' entry is returned in a locked state on success.
273 * On failure the entry is not locked and a negative err-code is returned.
274 * The caller must use ipc_rcu_putref() to free the identifier.
276 * Called with writer ipc_ids.rwsem held.
278 int ipc_addid(struct ipc_ids
*ids
, struct kern_ipc_perm
*new, int limit
)
284 /* 1) Initialize the refcount so that ipc_rcu_putref works */
285 refcount_set(&new->refcount
, 1);
290 if (ids
->in_use
>= limit
)
293 idr_preload(GFP_KERNEL
);
295 spin_lock_init(&new->lock
);
297 spin_lock(&new->lock
);
299 current_euid_egid(&euid
, &egid
);
300 new->cuid
= new->uid
= euid
;
301 new->gid
= new->cgid
= egid
;
303 new->deleted
= false;
305 idx
= ipc_idr_alloc(ids
, new);
308 if (idx
>= 0 && new->key
!= IPC_PRIVATE
) {
309 err
= rhashtable_insert_fast(&ids
->key_ht
, &new->khtnode
,
312 idr_remove(&ids
->ipcs_idr
, idx
);
318 spin_unlock(&new->lock
);
324 if (idx
> ids
->max_idx
)
330 * ipcget_new - create a new ipc object
332 * @ids: ipc identifier set
333 * @ops: the actual creation routine to call
334 * @params: its parameters
336 * This routine is called by sys_msgget, sys_semget() and sys_shmget()
337 * when the key is IPC_PRIVATE.
339 static int ipcget_new(struct ipc_namespace
*ns
, struct ipc_ids
*ids
,
340 const struct ipc_ops
*ops
, struct ipc_params
*params
)
344 down_write(&ids
->rwsem
);
345 err
= ops
->getnew(ns
, params
);
346 up_write(&ids
->rwsem
);
351 * ipc_check_perms - check security and permissions for an ipc object
353 * @ipcp: ipc permission set
354 * @ops: the actual security routine to call
355 * @params: its parameters
357 * This routine is called by sys_msgget(), sys_semget() and sys_shmget()
358 * when the key is not IPC_PRIVATE and that key already exists in the
361 * On success, the ipc id is returned.
363 * It is called with ipc_ids.rwsem and ipcp->lock held.
365 static int ipc_check_perms(struct ipc_namespace
*ns
,
366 struct kern_ipc_perm
*ipcp
,
367 const struct ipc_ops
*ops
,
368 struct ipc_params
*params
)
372 if (ipcperms(ns
, ipcp
, params
->flg
))
375 err
= ops
->associate(ipcp
, params
->flg
);
384 * ipcget_public - get an ipc object or create a new one
386 * @ids: ipc identifier set
387 * @ops: the actual creation routine to call
388 * @params: its parameters
390 * This routine is called by sys_msgget, sys_semget() and sys_shmget()
391 * when the key is not IPC_PRIVATE.
392 * It adds a new entry if the key is not found and does some permission
393 * / security checkings if the key is found.
395 * On success, the ipc id is returned.
397 static int ipcget_public(struct ipc_namespace
*ns
, struct ipc_ids
*ids
,
398 const struct ipc_ops
*ops
, struct ipc_params
*params
)
400 struct kern_ipc_perm
*ipcp
;
401 int flg
= params
->flg
;
405 * Take the lock as a writer since we are potentially going to add
406 * a new entry + read locks are not "upgradable"
408 down_write(&ids
->rwsem
);
409 ipcp
= ipc_findkey(ids
, params
->key
);
412 if (!(flg
& IPC_CREAT
))
415 err
= ops
->getnew(ns
, params
);
417 /* ipc object has been locked by ipc_findkey() */
419 if (flg
& IPC_CREAT
&& flg
& IPC_EXCL
)
423 if (ops
->more_checks
)
424 err
= ops
->more_checks(ipcp
, params
);
427 * ipc_check_perms returns the IPC id on
430 err
= ipc_check_perms(ns
, ipcp
, ops
, params
);
434 up_write(&ids
->rwsem
);
440 * ipc_kht_remove - remove an ipc from the key hashtable
441 * @ids: ipc identifier set
442 * @ipcp: ipc perm structure containing the key to remove
444 * ipc_ids.rwsem (as a writer) and the spinlock for this ID are held
445 * before this function is called, and remain locked on the exit.
447 static void ipc_kht_remove(struct ipc_ids
*ids
, struct kern_ipc_perm
*ipcp
)
449 if (ipcp
->key
!= IPC_PRIVATE
)
450 WARN_ON_ONCE(rhashtable_remove_fast(&ids
->key_ht
, &ipcp
->khtnode
,
455 * ipc_search_maxidx - search for the highest assigned index
456 * @ids: ipc identifier set
457 * @limit: known upper limit for highest assigned index
459 * The function determines the highest assigned index in @ids. It is intended
460 * to be called when ids->max_idx needs to be updated.
461 * Updating ids->max_idx is necessary when the current highest index ipc
463 * If no ipc object is allocated, then -1 is returned.
465 * ipc_ids.rwsem needs to be held by the caller.
467 static int ipc_search_maxidx(struct ipc_ids
*ids
, int limit
)
476 for (; i
>= 0; i
--) {
477 tmpidx
= retval
| (1<<i
);
479 * "0" is a possible index value, thus search using
480 * e.g. 15,7,3,1,0 instead of 16,8,4,2,1.
483 if (idr_get_next(&ids
->ipcs_idr
, &tmpidx
))
490 * ipc_rmid - remove an ipc identifier
491 * @ids: ipc identifier set
492 * @ipcp: ipc perm structure containing the identifier to remove
494 * ipc_ids.rwsem (as a writer) and the spinlock for this ID are held
495 * before this function is called, and remain locked on the exit.
497 void ipc_rmid(struct ipc_ids
*ids
, struct kern_ipc_perm
*ipcp
)
499 int idx
= ipcid_to_idx(ipcp
->id
);
501 WARN_ON_ONCE(idr_remove(&ids
->ipcs_idr
, idx
) != ipcp
);
502 ipc_kht_remove(ids
, ipcp
);
504 ipcp
->deleted
= true;
506 if (unlikely(idx
== ids
->max_idx
)) {
507 idx
= ids
->max_idx
-1;
509 idx
= ipc_search_maxidx(ids
, idx
);
515 * ipc_set_key_private - switch the key of an existing ipc to IPC_PRIVATE
516 * @ids: ipc identifier set
517 * @ipcp: ipc perm structure containing the key to modify
519 * ipc_ids.rwsem (as a writer) and the spinlock for this ID are held
520 * before this function is called, and remain locked on the exit.
522 void ipc_set_key_private(struct ipc_ids
*ids
, struct kern_ipc_perm
*ipcp
)
524 ipc_kht_remove(ids
, ipcp
);
525 ipcp
->key
= IPC_PRIVATE
;
528 bool ipc_rcu_getref(struct kern_ipc_perm
*ptr
)
530 return refcount_inc_not_zero(&ptr
->refcount
);
533 void ipc_rcu_putref(struct kern_ipc_perm
*ptr
,
534 void (*func
)(struct rcu_head
*head
))
536 if (!refcount_dec_and_test(&ptr
->refcount
))
539 call_rcu(&ptr
->rcu
, func
);
543 * ipcperms - check ipc permissions
545 * @ipcp: ipc permission set
546 * @flag: desired permission set
548 * Check user, group, other permissions for access
549 * to ipc resources. return 0 if allowed
551 * @flag will most probably be 0 or ``S_...UGO`` from <linux/stat.h>
553 int ipcperms(struct ipc_namespace
*ns
, struct kern_ipc_perm
*ipcp
, short flag
)
555 kuid_t euid
= current_euid();
556 int requested_mode
, granted_mode
;
559 requested_mode
= (flag
>> 6) | (flag
>> 3) | flag
;
560 granted_mode
= ipcp
->mode
;
561 if (uid_eq(euid
, ipcp
->cuid
) ||
562 uid_eq(euid
, ipcp
->uid
))
564 else if (in_group_p(ipcp
->cgid
) || in_group_p(ipcp
->gid
))
566 /* is there some bit set in requested_mode but not in granted_mode? */
567 if ((requested_mode
& ~granted_mode
& 0007) &&
568 !ns_capable(ns
->user_ns
, CAP_IPC_OWNER
))
571 return security_ipc_permission(ipcp
, flag
);
575 * Functions to convert between the kern_ipc_perm structure and the
576 * old/new ipc_perm structures
580 * kernel_to_ipc64_perm - convert kernel ipc permissions to user
581 * @in: kernel permissions
582 * @out: new style ipc permissions
584 * Turn the kernel object @in into a set of permissions descriptions
585 * for returning to userspace (@out).
587 void kernel_to_ipc64_perm(struct kern_ipc_perm
*in
, struct ipc64_perm
*out
)
590 out
->uid
= from_kuid_munged(current_user_ns(), in
->uid
);
591 out
->gid
= from_kgid_munged(current_user_ns(), in
->gid
);
592 out
->cuid
= from_kuid_munged(current_user_ns(), in
->cuid
);
593 out
->cgid
= from_kgid_munged(current_user_ns(), in
->cgid
);
594 out
->mode
= in
->mode
;
599 * ipc64_perm_to_ipc_perm - convert new ipc permissions to old
600 * @in: new style ipc permissions
601 * @out: old style ipc permissions
603 * Turn the new style permissions object @in into a compatibility
604 * object and store it into the @out pointer.
606 void ipc64_perm_to_ipc_perm(struct ipc64_perm
*in
, struct ipc_perm
*out
)
609 SET_UID(out
->uid
, in
->uid
);
610 SET_GID(out
->gid
, in
->gid
);
611 SET_UID(out
->cuid
, in
->cuid
);
612 SET_GID(out
->cgid
, in
->cgid
);
613 out
->mode
= in
->mode
;
618 * ipc_obtain_object_idr
619 * @ids: ipc identifier set
620 * @id: ipc id to look for
622 * Look for an id in the ipc ids idr and return associated ipc object.
624 * Call inside the RCU critical section.
625 * The ipc object is *not* locked on exit.
627 struct kern_ipc_perm
*ipc_obtain_object_idr(struct ipc_ids
*ids
, int id
)
629 struct kern_ipc_perm
*out
;
630 int idx
= ipcid_to_idx(id
);
632 out
= idr_find(&ids
->ipcs_idr
, idx
);
634 return ERR_PTR(-EINVAL
);
640 * ipc_obtain_object_check
641 * @ids: ipc identifier set
642 * @id: ipc id to look for
644 * Similar to ipc_obtain_object_idr() but also checks the ipc object
647 * Call inside the RCU critical section.
648 * The ipc object is *not* locked on exit.
650 struct kern_ipc_perm
*ipc_obtain_object_check(struct ipc_ids
*ids
, int id
)
652 struct kern_ipc_perm
*out
= ipc_obtain_object_idr(ids
, id
);
657 if (ipc_checkid(out
, id
))
658 return ERR_PTR(-EINVAL
);
664 * ipcget - Common sys_*get() code
666 * @ids: ipc identifier set
667 * @ops: operations to be called on ipc object creation, permission checks
669 * @params: the parameters needed by the previous operations.
671 * Common routine called by sys_msgget(), sys_semget() and sys_shmget().
673 int ipcget(struct ipc_namespace
*ns
, struct ipc_ids
*ids
,
674 const struct ipc_ops
*ops
, struct ipc_params
*params
)
676 if (params
->key
== IPC_PRIVATE
)
677 return ipcget_new(ns
, ids
, ops
, params
);
679 return ipcget_public(ns
, ids
, ops
, params
);
683 * ipc_update_perm - update the permissions of an ipc object
684 * @in: the permission given as input.
685 * @out: the permission of the ipc to set.
687 int ipc_update_perm(struct ipc64_perm
*in
, struct kern_ipc_perm
*out
)
689 kuid_t uid
= make_kuid(current_user_ns(), in
->uid
);
690 kgid_t gid
= make_kgid(current_user_ns(), in
->gid
);
691 if (!uid_valid(uid
) || !gid_valid(gid
))
696 out
->mode
= (out
->mode
& ~S_IRWXUGO
)
697 | (in
->mode
& S_IRWXUGO
);
703 * ipcctl_obtain_check - retrieve an ipc object and check permissions
705 * @ids: the table of ids where to look for the ipc
706 * @id: the id of the ipc to retrieve
707 * @cmd: the cmd to check
708 * @perm: the permission to set
709 * @extra_perm: one extra permission parameter used by msq
711 * This function does some common audit and permissions check for some IPC_XXX
712 * cmd and is called from semctl_down, shmctl_down and msgctl_down.
715 * - retrieves the ipc object with the given id in the given table.
716 * - performs some audit and permission check, depending on the given cmd
717 * - returns a pointer to the ipc object or otherwise, the corresponding
720 * Call holding the both the rwsem and the rcu read lock.
722 struct kern_ipc_perm
*ipcctl_obtain_check(struct ipc_namespace
*ns
,
723 struct ipc_ids
*ids
, int id
, int cmd
,
724 struct ipc64_perm
*perm
, int extra_perm
)
728 struct kern_ipc_perm
*ipcp
;
730 ipcp
= ipc_obtain_object_check(ids
, id
);
738 audit_ipc_set_perm(extra_perm
, perm
->uid
,
739 perm
->gid
, perm
->mode
);
741 euid
= current_euid();
742 if (uid_eq(euid
, ipcp
->cuid
) || uid_eq(euid
, ipcp
->uid
) ||
743 ns_capable(ns
->user_ns
, CAP_SYS_ADMIN
))
744 return ipcp
; /* successful lookup */
749 #ifdef CONFIG_ARCH_WANT_IPC_PARSE_VERSION
753 * ipc_parse_version - ipc call version
754 * @cmd: pointer to command
756 * Return IPC_64 for new style IPC and IPC_OLD for old style IPC.
757 * The @cmd value is turned from an encoding command and version into
758 * just the command code.
760 int ipc_parse_version(int *cmd
)
770 #endif /* CONFIG_ARCH_WANT_IPC_PARSE_VERSION */
772 #ifdef CONFIG_PROC_FS
773 struct ipc_proc_iter
{
774 struct ipc_namespace
*ns
;
775 struct pid_namespace
*pid_ns
;
776 struct ipc_proc_iface
*iface
;
779 struct pid_namespace
*ipc_seq_pid_ns(struct seq_file
*s
)
781 struct ipc_proc_iter
*iter
= s
->private;
786 * sysvipc_find_ipc - Find and lock the ipc structure based on seq pos
787 * @ids: ipc identifier set
788 * @pos: expected position
790 * The function finds an ipc structure, based on the sequence file
791 * position @pos. If there is no ipc structure at position @pos, then
792 * the successor is selected.
793 * If a structure is found, then it is locked (both rcu_read_lock() and
794 * ipc_lock_object()) and @pos is set to the position needed to locate
795 * the found ipc structure.
796 * If nothing is found (i.e. EOF), @pos is not modified.
798 * The function returns the found ipc structure, or NULL at EOF.
800 static struct kern_ipc_perm
*sysvipc_find_ipc(struct ipc_ids
*ids
, loff_t
*pos
)
803 struct kern_ipc_perm
*ipc
;
805 /* convert from position to idr index -> "-1" */
808 ipc
= idr_get_next(&ids
->ipcs_idr
, &tmpidx
);
811 ipc_lock_object(ipc
);
813 /* convert from idr index to position -> "+1" */
819 static void *sysvipc_proc_next(struct seq_file
*s
, void *it
, loff_t
*pos
)
821 struct ipc_proc_iter
*iter
= s
->private;
822 struct ipc_proc_iface
*iface
= iter
->iface
;
823 struct kern_ipc_perm
*ipc
= it
;
825 /* If we had an ipc id locked before, unlock it */
826 if (ipc
&& ipc
!= SEQ_START_TOKEN
)
829 /* Next -> search for *pos+1 */
831 return sysvipc_find_ipc(&iter
->ns
->ids
[iface
->ids
], pos
);
835 * File positions: pos 0 -> header, pos n -> ipc idx = n - 1.
836 * SeqFile iterator: iterator value locked ipc pointer or SEQ_TOKEN_START.
838 static void *sysvipc_proc_start(struct seq_file
*s
, loff_t
*pos
)
840 struct ipc_proc_iter
*iter
= s
->private;
841 struct ipc_proc_iface
*iface
= iter
->iface
;
844 ids
= &iter
->ns
->ids
[iface
->ids
];
847 * Take the lock - this will be released by the corresponding
850 down_read(&ids
->rwsem
);
852 /* pos < 0 is invalid */
856 /* pos == 0 means header */
858 return SEQ_START_TOKEN
;
860 /* Otherwise return the correct ipc structure */
861 return sysvipc_find_ipc(ids
, pos
);
864 static void sysvipc_proc_stop(struct seq_file
*s
, void *it
)
866 struct kern_ipc_perm
*ipc
= it
;
867 struct ipc_proc_iter
*iter
= s
->private;
868 struct ipc_proc_iface
*iface
= iter
->iface
;
871 /* If we had a locked structure, release it */
872 if (ipc
&& ipc
!= SEQ_START_TOKEN
)
875 ids
= &iter
->ns
->ids
[iface
->ids
];
876 /* Release the lock we took in start() */
877 up_read(&ids
->rwsem
);
880 static int sysvipc_proc_show(struct seq_file
*s
, void *it
)
882 struct ipc_proc_iter
*iter
= s
->private;
883 struct ipc_proc_iface
*iface
= iter
->iface
;
885 if (it
== SEQ_START_TOKEN
) {
886 seq_puts(s
, iface
->header
);
890 return iface
->show(s
, it
);
893 static const struct seq_operations sysvipc_proc_seqops
= {
894 .start
= sysvipc_proc_start
,
895 .stop
= sysvipc_proc_stop
,
896 .next
= sysvipc_proc_next
,
897 .show
= sysvipc_proc_show
,
900 static int sysvipc_proc_open(struct inode
*inode
, struct file
*file
)
902 struct ipc_proc_iter
*iter
;
904 iter
= __seq_open_private(file
, &sysvipc_proc_seqops
, sizeof(*iter
));
908 iter
->iface
= pde_data(inode
);
909 iter
->ns
= get_ipc_ns(current
->nsproxy
->ipc_ns
);
910 iter
->pid_ns
= get_pid_ns(task_active_pid_ns(current
));
915 static int sysvipc_proc_release(struct inode
*inode
, struct file
*file
)
917 struct seq_file
*seq
= file
->private_data
;
918 struct ipc_proc_iter
*iter
= seq
->private;
919 put_ipc_ns(iter
->ns
);
920 put_pid_ns(iter
->pid_ns
);
921 return seq_release_private(inode
, file
);
924 static const struct proc_ops sysvipc_proc_ops
= {
925 .proc_flags
= PROC_ENTRY_PERMANENT
,
926 .proc_open
= sysvipc_proc_open
,
927 .proc_read
= seq_read
,
928 .proc_lseek
= seq_lseek
,
929 .proc_release
= sysvipc_proc_release
,
931 #endif /* CONFIG_PROC_FS */