23 RCSID(
"$Id: 218b339cfbcec097eb96ba8df4b9f5756f794283 $")
30 #ifndef __EMSCRIPTEN__
38 #include <freeradius-devel/util/perm.h>
39 #include <freeradius-devel/util/sem.h>
40 #include <freeradius-devel/util/strerror.h>
41 #include <freeradius-devel/util/syserror.h>
43 #define DEFAULT_PROJ_ID ((int)'f')
57 ret = semctl(sem_id, 0, GETPID);
81 ret = semctl(sem_id, 0, IPC_STAT, &info);
89 *uid = info.sem_perm.uid;
105 struct semid_ds info;
107 ret = semctl(sem_id, 0, IPC_STAT, &info);
115 *gid = info.sem_perm.gid;
131 struct semid_ds info;
133 ret = semctl(sem_id, 0, IPC_STAT, &info);
141 *uid = info.sem_perm.cuid;
157 struct semid_ds info;
159 ret = semctl(sem_id, 0, IPC_STAT, &info);
167 *gid = info.sem_perm.cgid;
187 num = semctl(sem_id, 0, GETVAL);
193 if (num == 0)
return 1;
196 struct sembuf sop = {
199 .sem_flg = undo_on_exit * SEM_UNDO
202 if (semop(sem_id, &sop, 1) < 0) {
223 struct sembuf sop = {
226 .sem_flg = undo_on_exit * SEM_UNDO
229 if (semop(sem_id, &sop, 1) < 0) {
254 struct sembuf sops[2];
255 short flags_nonblock;
258 flags_nonblock = nonblock * IPC_NOWAIT;
259 flags_undo = undo_on_exit * SEM_UNDO;
268 sops[0].sem_flg = flags_nonblock;
272 sops[1].sem_flg = flags_nonblock | flags_undo;
274 if (semop(sem_id, sops, 2) < 0) {
278 int semop_err = errno;
284 if (semop_err == EAGAIN)
return 1;
295 ret = kill(sem_pid, 0);
296 if ((ret < 0) && (errno == ESRCH)) dead =
true;
299 if (
unlikely(!uid_str))
goto simple_error;
309 uid_str, gid_str, sem_pid, dead ?
" (dead)" :
"");
315 return (semop_err == EACCES ? -1 : -2);
331 if (semctl(sem_id, 0, IPC_RMID) < 0) {
341 char const *thing, uid_t expected, uid_t got)
343 char *expected_str, *got_str;
345 if (expected == got)
return true;
351 file, proj_id, thing);
361 fr_strerror_printf(
"Semaphore on \"%s\" ID 0x%x - %s is incorrect. Expected \"%s\", got \"%s\"",
362 file, proj_id, thing, expected_str, got_str);
371 char const *thing, gid_t expected, gid_t got)
373 char *expected_str, *got_str;
375 if (expected == got)
return true;
381 file, proj_id, thing);
391 fr_strerror_printf(
"Semaphore on \"%s\" ID 0x%x - %s is incorrect. Expected \"%s\", got \"%s\"",
392 file, proj_id, thing, expected_str, got_str);
421 int fr_sem_get(
char const *
file,
int proj_id, uid_t uid, gid_t gid,
bool check_perm,
bool must_exist)
425 bool seen_eexist =
false;
429 sem_key = ftok(
file, proj_id);
440 sem_id = semget(sem_key, 0, 0);
442 unsigned short mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
444 if (errno != ENOENT) {
450 if (must_exist)
return -4;
456 sem_id = semget(sem_key, 1, IPC_CREAT | IPC_EXCL | mode);
458 if (errno == EEXIST) {
474 struct semid_ds info = {
482 if (semctl(sem_id, 0, IPC_SET, &info) < 0) {
494 }
else if (check_perm) {
496 struct semid_ds info;
498 ret = semctl(sem_id, 0, IPC_STAT, &info);
505 if (info.sem_perm.mode & S_IWOTH) {
517 ((info.sem_perm.cuid != 0) && !
sem_check_uid(
file, proj_id,
"CUID", uid, info.sem_perm.cuid)) ||
519 ((info.sem_perm.cgid != 0) && !
sem_check_gid(
file, proj_id,
"CGID", gid, info.sem_perm.cgid))) {
char * fr_perm_gid_to_str(TALLOC_CTX *ctx, uid_t gid)
Print gid to a string.
char * fr_perm_uid_to_str(TALLOC_CTX *ctx, uid_t uid)
Print uid to a string.
int fr_sem_gid(uid_t *gid, int sem_id)
Return the GID that last operated on the semaphore.
int fr_sem_cgid(uid_t *gid, int sem_id)
Return the GID that created the semaphore.
int fr_sem_post(int sem_id, char const *file, bool undo_on_exit)
Decrement the semaphore by 1.
int fr_sem_wait(int sem_id, char const *file, bool undo_on_exit, bool nonblock)
Wait for a semaphore to reach 0, then increment it by 1.
int fr_sem_close(int sem_id, char const *file)
Remove the semaphore, this helps with permissions issues.
static bool sem_check_uid(char const *file, int proj_id, char const *thing, uid_t expected, uid_t got)
int fr_sem_cuid(uid_t *uid, int sem_id)
Return the UID that created the semaphore.
int fr_sem_uid(uid_t *uid, int sem_id)
Return the UID that last operated on the semaphore.
int fr_sem_pid(pid_t *pid, int sem_id)
Return the PID of the process that last operated on the semaphore.
static bool sem_check_gid(char const *file, int proj_id, char const *thing, gid_t expected, gid_t got)
int fr_sem_get(char const *file, int proj_id, uid_t uid, gid_t gid, bool check_perm, bool must_exist)
Returns a semid for the semaphore associated with the file.
int fr_sem_take(int sem_id, char const *file, bool undo_on_exit)
Increment the semaphore by 1.
Signals that can be sent to a request.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.