int krg_shm_flush_set(struct ipc_namespace *ns) { struct krgipc_ops *shmops; down_write(&sem_ids(ns).rw_mutex); shmops = shm_ids(ns).krgops; _kddm_flush_set(shmops->data_kddm_set, ipc_flusher, NULL); _kddm_flush_set(shmops->map_kddm_set, ipc_flusher, NULL); _kddm_flush_set(shmops->key_kddm_set, ipc_flusher, NULL); up_write(&sem_ids(ns).rw_mutex); return 0; }
static int newary(struct ipc_namespace *ns, struct ipc_params *params) { int id; int retval; struct sem_array *sma; int size; key_t key = params->key; int nsems = params->u.nsems; int semflg = params->flg; int i; if (!nsems) return -EINVAL; if (ns->used_sems + nsems > ns->sc_semmns) return -ENOSPC; size = sizeof (*sma) + nsems * sizeof (struct sem); sma = ipc_rcu_alloc(size); if (!sma) { return -ENOMEM; } memset (sma, 0, size); sma->sem_perm.mode = (semflg & S_IRWXUGO); sma->sem_perm.key = key; sma->sem_perm.security = NULL; retval = security_sem_alloc(sma); if (retval) { ipc_rcu_putref(sma); return retval; } id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni); if (id < 0) { security_sem_free(sma); ipc_rcu_putref(sma); return id; } ns->used_sems += nsems; sma->sem_base = (struct sem *) &sma[1]; for (i = 0; i < nsems; i++) { INIT_LIST_HEAD(&sma->sem_base[i].sem_pending); spin_lock_init(&sma->sem_base[i].lock); } sma->complex_count = 0; INIT_LIST_HEAD(&sma->sem_pending); INIT_LIST_HEAD(&sma->list_id); sma->sem_nsems = nsems; sma->sem_ctime = get_seconds(); sem_unlock(sma, -1); rcu_read_unlock(); return sma->sem_perm.id; }
/* * sem_lock_(check_) routines are called in the paths where the rw_mutex * is not held. */ static inline struct sem_array *sem_lock(struct ipc_namespace *ns, int id) { struct kern_ipc_perm *ipcp = ipc_lock(&sem_ids(ns), id); if (IS_ERR(ipcp)) return (struct sem_array *)ipcp; return container_of(ipcp, struct sem_array, sem_perm); }
static inline struct sem_array *sem_obtain_object(struct ipc_namespace *ns, int id) { struct kern_ipc_perm *ipcp = ipc_obtain_object(&sem_ids(ns), id); if (IS_ERR(ipcp)) return ERR_CAST(ipcp); return container_of(ipcp, struct sem_array, sem_perm); }
SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg) { struct ipc_namespace *ns; struct ipc_params sem_params; ns = current->nsproxy->ipc_ns; if (nsems < 0 || nsems > ns->sc_semmsl) return -EINVAL; sem_params.key = key; sem_params.flg = semflg; sem_params.u.nsems = nsems; return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params); }
SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg) { struct ipc_namespace *ns; struct ipc_ops sem_ops; struct ipc_params sem_params; ns = current->nsproxy->ipc_ns; if (nsems < 0 || nsems > ns->sc_semmsl) return -EINVAL; sem_ops.getnew = newary; sem_ops.associate = sem_security; sem_ops.more_checks = sem_more_checks; sem_params.key = key; sem_params.flg = semflg; sem_params.u.nsems = nsems; return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params); }
/* * sem_lock_(check_) routines are called in the paths where the rw_mutex * is not held. * * The caller holds the RCU read lock. */ static inline struct sem_array *sem_obtain_lock(struct ipc_namespace *ns, int id, struct sembuf *sops, int nsops, int *locknum) { struct kern_ipc_perm *ipcp; struct sem_array *sma; ipcp = ipc_obtain_object(&sem_ids(ns), id); if (IS_ERR(ipcp)) return ERR_CAST(ipcp); sma = container_of(ipcp, struct sem_array, sem_perm); *locknum = sem_lock(sma, sops, nsops); /* ipc_rmid() may have already freed the ID while sem_lock * was spinning: verify that the structure is still valid */ if (!ipcp->deleted) return container_of(ipcp, struct sem_array, sem_perm); sem_unlock(sma, *locknum); return ERR_PTR(-EINVAL); }
static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s) { ipc_rmid(&sem_ids(ns), &s->sem_perm); }
void sem_exit_ns(struct ipc_namespace *ns) { free_ipcs(ns, &sem_ids(ns), freeary); idr_destroy(&ns->ids[IPC_SEM_IDS].ipcs_idr); }
static #endif int newary(struct ipc_namespace *ns, struct ipc_params *params) { int id; int retval; struct sem_array *sma; int size; key_t key = params->key; int nsems = params->u.nsems; int semflg = params->flg; if (!nsems) return -EINVAL; if (ns->used_sems + nsems > ns->sc_semmns) return -ENOSPC; size = sizeof (*sma) + nsems * sizeof (struct sem); sma = ipc_rcu_alloc(size); if (!sma) { return -ENOMEM; } memset (sma, 0, size); sma->sem_perm.mode = (semflg & S_IRWXUGO); sma->sem_perm.key = key; sma->sem_perm.security = NULL; retval = security_sem_alloc(sma); if (retval) { ipc_rcu_putref(sma); return retval; } #ifdef CONFIG_KRG_IPC id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni, params->requested_id); #else id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni); #endif if (id < 0) { security_sem_free(sma); ipc_rcu_putref(sma); return id; } ns->used_sems += nsems; sma->sem_base = (struct sem *) &sma[1]; INIT_LIST_HEAD(&sma->sem_pending); INIT_LIST_HEAD(&sma->list_id); sma->sem_nsems = nsems; sma->sem_ctime = get_seconds(); #ifdef CONFIG_KRG_IPC INIT_LIST_HEAD(&sma->remote_sem_pending); if (is_krg_ipc(&sem_ids(ns))) { retval = krg_ipc_sem_newary(ns, sma); if (retval) { security_sem_free(sma); ipc_rcu_putref(sma); return retval; } } else sma->sem_perm.krgops = NULL; #endif sem_unlock(sma); return sma->sem_perm.id; }
void sem_exit_ns(struct ipc_namespace *ns) { free_ipcs(ns, &sem_ids(ns), freeary); }
void for_all_ipc_sem(string ipc_cb) { for_all_ipc_ids(init_nsproxy.ipc_ns, &sem_ids(init_nsproxy.ipc_ns), ipc_cb); }
struct sem_array *sem_lock(struct ipc_namespace *ns, int id) { struct kern_ipc_perm *ipcp = ipc_lock(&sem_ids(ns), id); return container_of(ipcp, struct sem_array, sem_perm); }