LCOV - code coverage report
Current view: top level - ipc - util.h (source / functions) Hit Total Coverage
Test: landlock.info Lines: 0 35 0.0 %
Date: 2021-04-22 12:43:58 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 */
       2             : /*
       3             :  * linux/ipc/util.h
       4             :  * Copyright (C) 1999 Christoph Rohland
       5             :  *
       6             :  * ipc helper functions (c) 1999 Manfred Spraul <manfred@colorfullife.com>
       7             :  * namespaces support.      2006 OpenVZ, SWsoft Inc.
       8             :  *                               Pavel Emelianov <xemul@openvz.org>
       9             :  */
      10             : 
      11             : #ifndef _IPC_UTIL_H
      12             : #define _IPC_UTIL_H
      13             : 
      14             : #include <linux/unistd.h>
      15             : #include <linux/err.h>
      16             : #include <linux/ipc_namespace.h>
      17             : 
      18             : /*
      19             :  * The IPC ID contains 2 separate numbers - index and sequence number.
      20             :  * By default,
      21             :  *   bits  0-14: index (32k, 15 bits)
      22             :  *   bits 15-30: sequence number (64k, 16 bits)
      23             :  *
      24             :  * When IPCMNI extension mode is turned on, the composition changes:
      25             :  *   bits  0-23: index (16M, 24 bits)
      26             :  *   bits 24-30: sequence number (128, 7 bits)
      27             :  */
      28             : #define IPCMNI_SHIFT            15
      29             : #define IPCMNI_EXTEND_SHIFT     24
      30             : #define IPCMNI_EXTEND_MIN_CYCLE (RADIX_TREE_MAP_SIZE * RADIX_TREE_MAP_SIZE)
      31             : #define IPCMNI                  (1 << IPCMNI_SHIFT)
      32             : #define IPCMNI_EXTEND           (1 << IPCMNI_EXTEND_SHIFT)
      33             : 
      34             : #ifdef CONFIG_SYSVIPC_SYSCTL
      35             : extern int ipc_mni;
      36             : extern int ipc_mni_shift;
      37             : extern int ipc_min_cycle;
      38             : 
      39             : #define ipcmni_seq_shift()      ipc_mni_shift
      40             : #define IPCMNI_IDX_MASK         ((1 << ipc_mni_shift) - 1)
      41             : 
      42             : #else /* CONFIG_SYSVIPC_SYSCTL */
      43             : 
      44             : #define ipc_mni                 IPCMNI
      45             : #define ipc_min_cycle           ((int)RADIX_TREE_MAP_SIZE)
      46             : #define ipcmni_seq_shift()      IPCMNI_SHIFT
      47             : #define IPCMNI_IDX_MASK         ((1 << IPCMNI_SHIFT) - 1)
      48             : #endif /* CONFIG_SYSVIPC_SYSCTL */
      49             : 
      50             : void sem_init(void);
      51             : void msg_init(void);
      52             : void shm_init(void);
      53             : 
      54             : struct ipc_namespace;
      55             : struct pid_namespace;
      56             : 
      57             : #ifdef CONFIG_POSIX_MQUEUE
      58             : extern void mq_clear_sbinfo(struct ipc_namespace *ns);
      59             : extern void mq_put_mnt(struct ipc_namespace *ns);
      60             : #else
      61             : static inline void mq_clear_sbinfo(struct ipc_namespace *ns) { }
      62             : static inline void mq_put_mnt(struct ipc_namespace *ns) { }
      63             : #endif
      64             : 
      65             : #ifdef CONFIG_SYSVIPC
      66             : void sem_init_ns(struct ipc_namespace *ns);
      67             : void msg_init_ns(struct ipc_namespace *ns);
      68             : void shm_init_ns(struct ipc_namespace *ns);
      69             : 
      70             : void sem_exit_ns(struct ipc_namespace *ns);
      71             : void msg_exit_ns(struct ipc_namespace *ns);
      72             : void shm_exit_ns(struct ipc_namespace *ns);
      73             : #else
      74             : static inline void sem_init_ns(struct ipc_namespace *ns) { }
      75             : static inline void msg_init_ns(struct ipc_namespace *ns) { }
      76             : static inline void shm_init_ns(struct ipc_namespace *ns) { }
      77             : 
      78             : static inline void sem_exit_ns(struct ipc_namespace *ns) { }
      79             : static inline void msg_exit_ns(struct ipc_namespace *ns) { }
      80             : static inline void shm_exit_ns(struct ipc_namespace *ns) { }
      81             : #endif
      82             : 
      83             : /*
      84             :  * Structure that holds the parameters needed by the ipc operations
      85             :  * (see after)
      86             :  */
      87             : struct ipc_params {
      88             :         key_t key;
      89             :         int flg;
      90             :         union {
      91             :                 size_t size;    /* for shared memories */
      92             :                 int nsems;      /* for semaphores */
      93             :         } u;                    /* holds the getnew() specific param */
      94             : };
      95             : 
      96             : /*
      97             :  * Structure that holds some ipc operations. This structure is used to unify
      98             :  * the calls to sys_msgget(), sys_semget(), sys_shmget()
      99             :  *      . routine to call to create a new ipc object. Can be one of newque,
     100             :  *        newary, newseg
     101             :  *      . routine to call to check permissions for a new ipc object.
     102             :  *        Can be one of security_msg_associate, security_sem_associate,
     103             :  *        security_shm_associate
     104             :  *      . routine to call for an extra check if needed
     105             :  */
     106             : struct ipc_ops {
     107             :         int (*getnew)(struct ipc_namespace *, struct ipc_params *);
     108             :         int (*associate)(struct kern_ipc_perm *, int);
     109             :         int (*more_checks)(struct kern_ipc_perm *, struct ipc_params *);
     110             : };
     111             : 
     112             : struct seq_file;
     113             : struct ipc_ids;
     114             : 
     115             : void ipc_init_ids(struct ipc_ids *ids);
     116             : #ifdef CONFIG_PROC_FS
     117             : void __init ipc_init_proc_interface(const char *path, const char *header,
     118             :                 int ids, int (*show)(struct seq_file *, void *));
     119             : struct pid_namespace *ipc_seq_pid_ns(struct seq_file *);
     120             : #else
     121             : #define ipc_init_proc_interface(path, header, ids, show) do {} while (0)
     122             : #endif
     123             : 
     124             : #define IPC_SEM_IDS     0
     125             : #define IPC_MSG_IDS     1
     126             : #define IPC_SHM_IDS     2
     127             : 
     128             : #define ipcid_to_idx(id)  ((id) & IPCMNI_IDX_MASK)
     129             : #define ipcid_to_seqx(id) ((id) >> ipcmni_seq_shift())
     130             : #define ipcid_seq_max()   (INT_MAX >> ipcmni_seq_shift())
     131             : 
     132             : /* must be called with ids->rwsem acquired for writing */
     133             : int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
     134             : 
     135             : /* must be called with both locks acquired. */
     136             : void ipc_rmid(struct ipc_ids *, struct kern_ipc_perm *);
     137             : 
     138             : /* must be called with both locks acquired. */
     139             : void ipc_set_key_private(struct ipc_ids *, struct kern_ipc_perm *);
     140             : 
     141             : /* must be called with ipcp locked */
     142             : int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flg);
     143             : 
     144             : /**
     145             :  * ipc_get_maxidx - get the highest assigned index
     146             :  * @ids: ipc identifier set
     147             :  *
     148             :  * Called with ipc_ids.rwsem held for reading.
     149             :  */
     150           0 : static inline int ipc_get_maxidx(struct ipc_ids *ids)
     151             : {
     152           0 :         if (ids->in_use == 0)
     153             :                 return -1;
     154             : 
     155           0 :         if (ids->in_use == ipc_mni)
     156           0 :                 return ipc_mni - 1;
     157             : 
     158           0 :         return ids->max_idx;
     159             : }
     160             : 
     161             : /*
     162             :  * For allocation that need to be freed by RCU.
     163             :  * Objects are reference counted, they start with reference count 1.
     164             :  * getref increases the refcount, the putref call that reduces the recount
     165             :  * to 0 schedules the rcu destruction. Caller must guarantee locking.
     166             :  *
     167             :  * refcount is initialized by ipc_addid(), before that point call_rcu()
     168             :  * must be used.
     169             :  */
     170             : bool ipc_rcu_getref(struct kern_ipc_perm *ptr);
     171             : void ipc_rcu_putref(struct kern_ipc_perm *ptr,
     172             :                         void (*func)(struct rcu_head *head));
     173             : 
     174             : struct kern_ipc_perm *ipc_obtain_object_idr(struct ipc_ids *ids, int id);
     175             : 
     176             : void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
     177             : void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
     178             : int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out);
     179             : struct kern_ipc_perm *ipcctl_obtain_check(struct ipc_namespace *ns,
     180             :                                              struct ipc_ids *ids, int id, int cmd,
     181             :                                              struct ipc64_perm *perm, int extra_perm);
     182             : 
     183           0 : static inline void ipc_update_pid(struct pid **pos, struct pid *pid)
     184             : {
     185           0 :         struct pid *old = *pos;
     186           0 :         if (old != pid) {
     187           0 :                 *pos = get_pid(pid);
     188           0 :                 put_pid(old);
     189             :         }
     190           0 : }
     191             : 
     192             : #ifdef CONFIG_ARCH_WANT_IPC_PARSE_VERSION
     193             : int ipc_parse_version(int *cmd);
     194             : #endif
     195             : 
     196             : extern void free_msg(struct msg_msg *msg);
     197             : extern struct msg_msg *load_msg(const void __user *src, size_t len);
     198             : extern struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst);
     199             : extern int store_msg(void __user *dest, struct msg_msg *msg, size_t len);
     200             : 
     201           0 : static inline int ipc_checkid(struct kern_ipc_perm *ipcp, int id)
     202             : {
     203           0 :         return ipcid_to_seqx(id) != ipcp->seq;
     204             : }
     205             : 
     206           0 : static inline void ipc_lock_object(struct kern_ipc_perm *perm)
     207             : {
     208           0 :         spin_lock(&perm->lock);
     209           0 : }
     210             : 
     211           0 : static inline void ipc_unlock_object(struct kern_ipc_perm *perm)
     212             : {
     213           0 :         spin_unlock(&perm->lock);
     214           0 : }
     215             : 
     216           0 : static inline void ipc_assert_locked_object(struct kern_ipc_perm *perm)
     217             : {
     218           0 :         assert_spin_locked(&perm->lock);
     219           0 : }
     220             : 
     221           0 : static inline void ipc_unlock(struct kern_ipc_perm *perm)
     222             : {
     223           0 :         ipc_unlock_object(perm);
     224           0 :         rcu_read_unlock();
     225           0 : }
     226             : 
     227             : /*
     228             :  * ipc_valid_object() - helper to sort out IPC_RMID races for codepaths
     229             :  * where the respective ipc_ids.rwsem is not being held down.
     230             :  * Checks whether the ipc object is still around or if it's gone already, as
     231             :  * ipc_rmid() may have already freed the ID while the ipc lock was spinning.
     232             :  * Needs to be called with kern_ipc_perm.lock held -- exception made for one
     233             :  * checkpoint case at sys_semtimedop() as noted in code commentary.
     234             :  */
     235           0 : static inline bool ipc_valid_object(struct kern_ipc_perm *perm)
     236             : {
     237           0 :         return !perm->deleted;
     238             : }
     239             : 
     240             : struct kern_ipc_perm *ipc_obtain_object_check(struct ipc_ids *ids, int id);
     241             : int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
     242             :                         const struct ipc_ops *ops, struct ipc_params *params);
     243             : void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
     244             :                 void (*free)(struct ipc_namespace *, struct kern_ipc_perm *));
     245             : 
     246           0 : static inline int sem_check_semmni(struct ipc_namespace *ns) {
     247             :         /*
     248             :          * Check semmni range [0, ipc_mni]
     249             :          * semmni is the last element of sem_ctls[4] array
     250             :          */
     251           0 :         return ((ns->sem_ctls[3] < 0) || (ns->sem_ctls[3] > ipc_mni))
     252           0 :                 ? -ERANGE : 0;
     253             : }
     254             : 
     255             : #ifdef CONFIG_COMPAT
     256             : #include <linux/compat.h>
     257             : struct compat_ipc_perm {
     258             :         key_t key;
     259             :         __compat_uid_t uid;
     260             :         __compat_gid_t gid;
     261             :         __compat_uid_t cuid;
     262             :         __compat_gid_t cgid;
     263             :         compat_mode_t mode;
     264             :         unsigned short seq;
     265             : };
     266             : 
     267             : void to_compat_ipc_perm(struct compat_ipc_perm *, struct ipc64_perm *);
     268             : void to_compat_ipc64_perm(struct compat_ipc64_perm *, struct ipc64_perm *);
     269             : int get_compat_ipc_perm(struct ipc64_perm *, struct compat_ipc_perm __user *);
     270             : int get_compat_ipc64_perm(struct ipc64_perm *,
     271             :                           struct compat_ipc64_perm __user *);
     272             : 
     273           0 : static inline int compat_ipc_parse_version(int *cmd)
     274             : {
     275           0 :         int version = *cmd & IPC_64;
     276           0 :         *cmd &= ~IPC_64;
     277           0 :         return version;
     278             : }
     279             : 
     280             : long compat_ksys_old_semctl(int semid, int semnum, int cmd, int arg);
     281             : long compat_ksys_old_msgctl(int msqid, int cmd, void __user *uptr);
     282             : long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz,
     283             :                         compat_long_t msgtyp, int msgflg);
     284             : long compat_ksys_msgsnd(int msqid, compat_uptr_t msgp,
     285             :                        compat_ssize_t msgsz, int msgflg);
     286             : long compat_ksys_old_shmctl(int shmid, int cmd, void __user *uptr);
     287             : 
     288             : #endif
     289             : 
     290             : #endif

Generated by: LCOV version 1.14