23RCSID(
"$Id: c2e1cd5b7acf0a74b0b9c7c20645cdf0e14d091d $")
37#include <freeradius-devel/util/perm.h>
38#include <freeradius-devel/util/sem.h>
39#include <freeradius-devel/util/strerror.h>
40#include <freeradius-devel/util/syserror.h>
42#define DEFAULT_PROJ_ID ((int)'f')
56 ret = semctl(sem_id, 0, GETPID);
80 ret = semctl(sem_id, 0, IPC_STAT, &info);
88 *uid = info.sem_perm.uid;
104 struct semid_ds info;
106 ret = semctl(sem_id, 0, IPC_STAT, &info);
114 *gid = info.sem_perm.gid;
130 struct semid_ds info;
132 ret = semctl(sem_id, 0, IPC_STAT, &info);
140 *uid = info.sem_perm.cuid;
156 struct semid_ds info;
158 ret = semctl(sem_id, 0, IPC_STAT, &info);
166 *gid = info.sem_perm.cgid;
186 num = semctl(sem_id, 0, GETVAL);
192 if (num == 0)
return 1;
195 struct sembuf sop = {
198 .sem_flg = undo_on_exit * SEM_UNDO
201 if (semop(sem_id, &sop, 1) < 0) {
222 struct sembuf sop = {
225 .sem_flg = undo_on_exit * SEM_UNDO
228 if (semop(sem_id, &sop, 1) < 0) {
253 struct sembuf sops[2];
254 short flags_nonblock;
257 flags_nonblock = nonblock * IPC_NOWAIT;
258 flags_undo = undo_on_exit * SEM_UNDO;
267 sops[0].sem_flg = flags_nonblock;
271 sops[1].sem_flg = flags_nonblock | flags_undo;
273 if (semop(sem_id, sops, 2) < 0) {
277 int semop_err = errno;
283 if (semop_err == EAGAIN)
return 1;
294 ret = kill(sem_pid, 0);
295 if ((ret < 0) && (errno == ESRCH)) dead =
true;
298 if (
unlikely(!uid_str))
goto simple_error;
308 uid_str, gid_str, (
unsigned int) sem_pid, dead ?
" (dead)" :
"");
314 return (semop_err == EACCES ? -1 : -2);
330 if (semctl(sem_id, 0, IPC_RMID) < 0) {
340 char const *thing, uid_t expected, uid_t got)
342 char *expected_str, *got_str;
344 if (expected == got)
return true;
350 file, (
unsigned int) proj_id, thing);
360 fr_strerror_printf(
"Semaphore on \"%s\" ID 0x%x - %s is incorrect. Expected \"%s\", got \"%s\"",
361 file, (
unsigned int) proj_id, thing, expected_str, got_str);
370 char const *thing, gid_t expected, gid_t got)
372 char *expected_str, *got_str;
374 if (expected == got)
return true;
380 file, (
unsigned int) proj_id, thing);
390 fr_strerror_printf(
"Semaphore on \"%s\" ID 0x%x - %s is incorrect. Expected \"%s\", got \"%s\"",
391 file, (
unsigned int) proj_id, thing, expected_str, got_str);
420int fr_sem_get(
char const *
file,
int proj_id, uid_t uid, gid_t gid,
bool check_perm,
bool must_exist)
424 bool seen_eexist =
false;
428 sem_key = ftok(
file, proj_id);
439 sem_id = semget(sem_key, 0, 0);
441 unsigned short mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
443 if (errno != ENOENT) {
449 if (must_exist)
return -4;
455 sem_id = semget(sem_key, 1, IPC_CREAT | IPC_EXCL | mode);
457 if (errno == EEXIST) {
473 struct semid_ds info = {
481 if (semctl(sem_id, 0, IPC_SET, &info) < 0) {
493 }
else if (check_perm) {
495 struct semid_ds info;
497 ret = semctl(sem_id, 0, IPC_STAT, &info);
504 if (info.sem_perm.mode & S_IWOTH) {
506 file, (
unsigned int) proj_id);
516 ((info.sem_perm.cuid != 0) && !
sem_check_uid(
file, proj_id,
"CUID", uid, info.sem_perm.cuid)) ||
518 ((info.sem_perm.cgid != 0) && !
sem_check_gid(
file, proj_id,
"CGID", gid, info.sem_perm.cgid))) {
char * fr_perm_uid_to_str(TALLOC_CTX *ctx, uid_t uid)
Print uid to a string.
char * fr_perm_gid_to_str(TALLOC_CTX *ctx, uid_t gid)
Print gid 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.