Created
June 3, 2015 18:37
-
-
Save kikuchan/c7b645e1c0c7f7b7c1b0 to your computer and use it in GitHub Desktop.
A patch to run multiple (version of, if you want, ) PostgreSQL (with same uid) simultaneously on FreeBSD jail. (Change sysv_sem/shm policy to per jail basis)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/kern/sysv_sem.c b/kern/sysv_sem.c | |
index 53b63e0..25fe343 100644 | |
--- a/kern/sysv_sem.c | |
+++ b/kern/sysv_sem.c | |
@@ -506,6 +506,17 @@ semvalid(int semid, struct semid_kernel *semakptr) | |
semakptr->u.sem_perm.seq != IPCID_TO_SEQ(semid) ? EINVAL : 0); | |
} | |
+static int | |
+jail_check_semperm(td, semakptr) | |
+ struct thread *td; | |
+ struct semid_kernel *semakptr; | |
+{ | |
+ if (semakptr->cred->cr_prison != td->td_ucred->cr_prison) | |
+ return EACCES; | |
+ return 0; | |
+} | |
+ | |
+ | |
/* | |
* Note that the user-mode half of this passes a union, not a pointer. | |
*/ | |
@@ -612,6 +623,8 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, | |
} | |
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) | |
goto done2; | |
+ if ((error = jail_check_semperm(td, semakptr))) | |
+ goto done2; | |
#ifdef MAC | |
error = mac_sysvsem_check_semctl(cred, semakptr, cmd); | |
if (error != 0) | |
@@ -647,6 +660,8 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, | |
goto done2; | |
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M))) | |
goto done2; | |
+ if ((error = jail_check_semperm(td, semakptr))) | |
+ goto done2; | |
semakptr->u.sem_perm.cuid = cred->cr_uid; | |
semakptr->u.sem_perm.uid = cred->cr_uid; | |
semakptr->u.sem_perm.mode = 0; | |
@@ -682,6 +697,8 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, | |
goto done2; | |
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M))) | |
goto done2; | |
+ if ((error = jail_check_semperm(td, semakptr))) | |
+ goto done2; | |
sbuf = arg->buf; | |
semakptr->u.sem_perm.uid = sbuf->sem_perm.uid; | |
semakptr->u.sem_perm.gid = sbuf->sem_perm.gid; | |
@@ -695,6 +712,8 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, | |
goto done2; | |
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) | |
goto done2; | |
+ if ((error = jail_check_semperm(td, semakptr))) | |
+ goto done2; | |
bcopy(&semakptr->u, arg->buf, sizeof(struct semid_ds)); | |
break; | |
@@ -703,6 +722,8 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, | |
goto done2; | |
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) | |
goto done2; | |
+ if ((error = jail_check_semperm(td, semakptr))) | |
+ goto done2; | |
if (semnum < 0 || semnum >= semakptr->u.sem_nsems) { | |
error = EINVAL; | |
goto done2; | |
@@ -715,6 +736,8 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, | |
goto done2; | |
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) | |
goto done2; | |
+ if ((error = jail_check_semperm(td, semakptr))) | |
+ goto done2; | |
if (semnum < 0 || semnum >= semakptr->u.sem_nsems) { | |
error = EINVAL; | |
goto done2; | |
@@ -727,6 +750,8 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, | |
goto done2; | |
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) | |
goto done2; | |
+ if ((error = jail_check_semperm(td, semakptr))) | |
+ goto done2; | |
if (semnum < 0 || semnum >= semakptr->u.sem_nsems) { | |
error = EINVAL; | |
goto done2; | |
@@ -764,6 +789,8 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, | |
KASSERT(count == semakptr->u.sem_nsems, ("nsems changed")); | |
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) | |
goto done2; | |
+ if ((error = jail_check_semperm(td, semakptr))) | |
+ goto done2; | |
for (i = 0; i < semakptr->u.sem_nsems; i++) | |
array[i] = semakptr->u.sem_base[i].semval; | |
mtx_unlock(sema_mtxp); | |
@@ -776,6 +803,8 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, | |
goto done2; | |
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) | |
goto done2; | |
+ if ((error = jail_check_semperm(td, semakptr))) | |
+ goto done2; | |
if (semnum < 0 || semnum >= semakptr->u.sem_nsems) { | |
error = EINVAL; | |
goto done2; | |
@@ -788,6 +817,8 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, | |
goto done2; | |
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W))) | |
goto done2; | |
+ if ((error = jail_check_semperm(td, semakptr))) | |
+ goto done2; | |
if (semnum < 0 || semnum >= semakptr->u.sem_nsems) { | |
error = EINVAL; | |
goto done2; | |
@@ -820,6 +851,8 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, | |
KASSERT(count == semakptr->u.sem_nsems, ("nsems changed")); | |
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W))) | |
goto done2; | |
+ if ((error = jail_check_semperm(td, semakptr))) | |
+ goto done2; | |
for (i = 0; i < semakptr->u.sem_nsems; i++) { | |
usval = array[i]; | |
if (usval > seminfo.semvmx) { | |
@@ -872,7 +905,8 @@ sys_semget(struct thread *td, struct semget_args *uap) | |
if (key != IPC_PRIVATE) { | |
for (semid = 0; semid < seminfo.semmni; semid++) { | |
if ((sema[semid].u.sem_perm.mode & SEM_ALLOC) && | |
- sema[semid].u.sem_perm.key == key) | |
+ sema[semid].u.sem_perm.key == key && | |
+ sema[semid].cred->cr_prison == cred->cr_prison) | |
break; | |
} | |
if (semid < seminfo.semmni) { | |
@@ -1049,6 +1083,8 @@ sys_semop(struct thread *td, struct semop_args *uap) | |
error = EINVAL; | |
goto done2; | |
} | |
+ if ((error = jail_check_semperm(td, semakptr))) | |
+ goto done2; | |
/* | |
* Initial pass thru sops to see what permissions are needed. | |
* Also perform any checks that don't need repeating on each | |
diff --git a/kern/sysv_shm.c b/kern/sysv_shm.c | |
index 9a111d7..e663462 100644 | |
--- a/kern/sysv_shm.c | |
+++ b/kern/sysv_shm.c | |
@@ -121,7 +121,7 @@ struct shmmap_state { | |
}; | |
static void shm_deallocate_segment(struct shmid_kernel *); | |
-static int shm_find_segment_by_key(key_t); | |
+static int shm_find_segment_by_key(key_t, struct ucred *); | |
static struct shmid_kernel *shm_find_segment_by_shmid(int); | |
static struct shmid_kernel *shm_find_segment_by_shmidx(int); | |
static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *); | |
@@ -186,14 +186,26 @@ SYSCTL_PROC(_kern_ipc, OID_AUTO, shmsegs, CTLTYPE_OPAQUE | CTLFLAG_RD, | |
"Current number of shared memory segments allocated"); | |
static int | |
-shm_find_segment_by_key(key) | |
+jail_check_shmctl(td, shmseg) | |
+ struct thread *td; | |
+ struct shmid_kernel *shmseg; | |
+{ | |
+ if (shmseg->cred->cr_prison != td->td_ucred->cr_prison) | |
+ return EACCES; | |
+ return 0; | |
+} | |
+ | |
+static int | |
+shm_find_segment_by_key(key, cred) | |
key_t key; | |
+ struct ucred *cred; | |
{ | |
int i; | |
for (i = 0; i < shmalloced; i++) | |
if ((shmsegs[i].u.shm_perm.mode & SHMSEG_ALLOCATED) && | |
- shmsegs[i].u.shm_perm.key == key) | |
+ shmsegs[i].u.shm_perm.key == key && | |
+ shmsegs[i].cred->cr_prison == cred->cr_prison) | |
return (i); | |
return (-1); | |
} | |
@@ -369,6 +381,7 @@ kern_shmat(td, shmid, shmaddr, shmflg) | |
} | |
error = ipcperm(td, &shmseg->u.shm_perm, | |
(shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W); | |
+ if (!error) error = jail_check_shmctl(td, shmseg); | |
if (error) | |
goto done2; | |
#ifdef MAC | |
@@ -503,6 +516,7 @@ kern_shmctl(td, shmid, cmd, buf, bufsz) | |
case SHM_STAT: | |
case IPC_STAT: | |
error = ipcperm(td, &shmseg->u.shm_perm, IPC_R); | |
+ if (!error) error = jail_check_shmctl(td, shmseg); | |
if (error) | |
goto done2; | |
memcpy(buf, &shmseg->u, sizeof(struct shmid_ds)); | |
@@ -516,6 +530,7 @@ kern_shmctl(td, shmid, cmd, buf, bufsz) | |
shmid = (struct shmid_ds *)buf; | |
error = ipcperm(td, &shmseg->u.shm_perm, IPC_M); | |
+ if (!error) error = jail_check_shmctl(td, shmseg); | |
if (error) | |
goto done2; | |
shmseg->u.shm_perm.uid = shmid->shm_perm.uid; | |
@@ -528,6 +543,7 @@ kern_shmctl(td, shmid, cmd, buf, bufsz) | |
} | |
case IPC_RMID: | |
error = ipcperm(td, &shmseg->u.shm_perm, IPC_M); | |
+ if (!error) error = jail_check_shmctl(td, shmseg); | |
if (error) | |
goto done2; | |
shmseg->u.shm_perm.key = IPC_PRIVATE; | |
@@ -762,7 +778,7 @@ sys_shmget(td, uap) | |
mode = uap->shmflg & ACCESSPERMS; | |
if (uap->key != IPC_PRIVATE) { | |
again: | |
- segnum = shm_find_segment_by_key(uap->key); | |
+ segnum = shm_find_segment_by_key(uap->key, td->td_ucred); | |
if (segnum >= 0) { | |
error = shmget_existing(td, uap, mode, segnum); | |
if (error == EAGAIN) | |
@@ -1005,6 +1021,7 @@ oshmctl(struct thread *td, struct oshmctl_args *uap) | |
switch (uap->cmd) { | |
case IPC_STAT: | |
error = ipcperm(td, &shmseg->u.shm_perm, IPC_R); | |
+ if (!error) error = jail_check_shmctl(td, shmseg); | |
if (error) | |
goto done2; | |
#ifdef MAC |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment