diff --git a/src/libstore/unix/build/darwin-derivation-builder.cc b/src/libstore/unix/build/darwin-derivation-builder.cc index 2ec3ea845..701da9513 100644 --- a/src/libstore/unix/build/darwin-derivation-builder.cc +++ b/src/libstore/unix/build/darwin-derivation-builder.cc @@ -5,17 +5,23 @@ # include # include # include +# include +# include /* This definition is undocumented but depended upon by all major browsers. */ extern "C" int sandbox_init_with_parameters(const char * profile, uint64_t flags, const char * const parameters[], char ** errorbuf); -/* Darwin IPC cleanup structures and constants */ +/* Darwin IPC structures and constants */ # define IPCS_MAGIC 0x00000001 # define IPCS_SHM_ITER 0x00000002 +# define IPCS_SEM_ITER 0x00000020 +# define IPCS_MSG_ITER 0x00000200 # define IPCS_SHM_SYSCTL "kern.sysv.ipcs.shm" +# define IPCS_MSG_SYSCTL "kern.sysv.ipcs.msg" +# define IPCS_SEM_SYSCTL "kern.sysv.ipcs.sem" -struct IPCS_command +struct IpcsCommand { uint32_t ipcs_magic; uint32_t ipcs_op; @@ -223,31 +229,97 @@ struct DarwinDerivationBuilder : DerivationBuilderImpl void cleanupSysVIPCForUser(uid_t uid) { - struct IPCS_command ic; - struct shmid_ds shm_ds; + struct IpcsCommand ic; size_t ic_size = sizeof(ic); + // IPC ids to cleanup + std::vector shm_ids, msg_ids, sem_ids; - ic.ipcs_magic = IPCS_MAGIC; - ic.ipcs_op = IPCS_SHM_ITER; - ic.ipcs_cursor = 0; - ic.ipcs_data = &shm_ds; - ic.ipcs_datalen = sizeof(shm_ds); + { + struct shmid_ds shm_ds; + ic.ipcs_magic = IPCS_MAGIC; + ic.ipcs_op = IPCS_SHM_ITER; + ic.ipcs_cursor = 0; + ic.ipcs_data = &shm_ds; + ic.ipcs_datalen = sizeof(shm_ds); - while (true) { - memset(&shm_ds, 0, sizeof(shm_ds)); + while (true) { + memset(&shm_ds, 0, sizeof(shm_ds)); - if (sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size) != 0) { - break; - } + if (sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size) != 0) { + break; + } - if (shm_ds.shm_perm.uid == uid) { - int shmid = shmget(shm_ds.shm_perm._key, 0, 0); - if (shmid != -1) { - if (shmctl(shmid, IPC_RMID, NULL) == 0) - debug("removed shared memory segment with shmid %d (key: 0x%x)", shmid, shm_ds.shm_perm._key); + if (shm_ds.shm_perm.uid == uid) { + int shmid = shmget(shm_ds.shm_perm._key, 0, 0); + if (shmid != -1) { + shm_ids.push_back(shmid); + } } } } + + for (auto id : shm_ids) { + if (shmctl(id, IPC_RMID, NULL) == 0) + debug("removed shared memory segment with shmid %d", id); + } + + { + struct msqid_ds msg_ds; + ic.ipcs_magic = IPCS_MAGIC; + ic.ipcs_op = IPCS_MSG_ITER; + ic.ipcs_cursor = 0; + ic.ipcs_data = &msg_ds; + ic.ipcs_datalen = sizeof(msg_ds); + + while (true) { + memset(&msg_ds, 0, sizeof(msg_ds)); + + if (sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size) != 0) { + break; + } + + if (msg_ds.msg_perm.uid == uid) { + int msgid = msgget(msg_ds.msg_perm._key, 0); + if (msgid != -1) { + msg_ids.push_back(msgid); + } + } + } + } + + for (auto id : msg_ids) { + if (msgctl(id, IPC_RMID, NULL) == 0) + debug("removed message queue with msgid %d", id); + } + + { + struct semid_ds sem_ds; + ic.ipcs_magic = IPCS_MAGIC; + ic.ipcs_op = IPCS_SEM_ITER; + ic.ipcs_cursor = 0; + ic.ipcs_data = &sem_ds; + ic.ipcs_datalen = sizeof(sem_ds); + + while (true) { + memset(&sem_ds, 0, sizeof(sem_ds)); + + if (sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size) != 0) { + break; + } + + if (sem_ds.sem_perm.uid == uid) { + int semid = semget(sem_ds.sem_perm._key, 0, 0); + if (semid != -1) { + sem_ids.push_back(semid); + } + } + } + } + + for (auto id : sem_ids) { + if (semctl(id, 0, IPC_RMID) == 0) + debug("removed semaphore with semid %d", id); + } } void killSandbox(bool getStats) override