/* SAMHAIN file system integrity testing */ /* Copyright (C) 1999, 2000, 2015 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config_xor.h" #include #include #if defined(HAVE_SYS_SEM_H) && defined(HAVE_UNISTD_H) #include "samhain.h" #include "sh_sem.h" #include "sh_error_min.h" #include #include #include #include #include #include #undef FIL__ #define FIL__ _("sh_sem.c") typedef enum { exit_ok = 0, exit_fail = 1, exit_time = 2, exit_err = 3 } sh_estat; #if 0 /* FreeBSD 6.1 defines this in too... */ #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) /* union semun is defined by including */ #else /* according to X/OPEN we have to define it ourselves */ union semun { int val; struct semid_ds *buf; unsigned short *array; }; #endif #endif #define SH_SEMVMX 32767 static int get_semaphore (void) { key_t key = ftok(DEFAULT_DATAROOT, '#'); int semid; if (key < 0) return -1; semid = semget (key, 0, IPC_PRIVATE); if (semid < 0) return -1; return semid; } static void sem_purge(int sem_id) { if (sem_id != -1) semctl(sem_id, 0, IPC_RMID, (int)0); return; } static void sem_purge_stale() { int stale_ID = get_semaphore(); if (stale_ID != -1) sem_purge(stale_ID); return; } static int report_err(int errnum, char * file, int line, char * func) { char errbuf[SH_ERRBUF_SIZE]; sh_error_message(errnum, errbuf, sizeof(errbuf)); sh_error_handle((-1), file, line, errnum, MSG_E_SUBGEN, errbuf, func); return -1; } static int init_semaphore (int nsems) { int i; mode_t mask; int semid; int errnum; key_t key = ftok(DEFAULT_DATAROOT, '#'); if (key < 0) return report_err(errno, FIL__, __LINE__, _("ftok")); mask = umask(0); semid = semget (key, nsems, IPC_CREAT | IPC_EXCL | 0660); errnum = errno; umask(mask); if (semid < 0) return report_err(errnum, FIL__, __LINE__, _("semget")); for (i=0; i= 0) { val = (val > SH_SEMVMX) ? SH_SEMVMX : val; /* signed short int maxval */ sem_set(sem_ID, 1, (int) val); } SH_SEMAPHORE_UNLOCK(sem_ID); return; } void sh_sem_close() { SH_SEMAPHORE_PURGE(sem_ID); return; } static volatile int alarm_triggered = 0; static void alarm_handler(int sig) { (void) sig; alarm_triggered = 1; return; } int sh_sem_wait(const char * wait) { int rc, flag = 0; int time_wait = atoi(wait); SH_SEMAPHORE_EXTERN(sem_id); if (time_wait < 0) { time_wait *= (-1); time_wait -= 1; flag = 1; } if (time_wait < 0 || time_wait > (24*3600)) { fprintf(stderr, _("Invalid argument <%d>.\n"), time_wait); _exit(exit_err); } if (sem_id == -1) { if (flag && errno == ENOENT) { do { retry_msleep(1, 0); rc = get_semaphore(); } while (rc == -1); sem_id = rc; } else { if (errno == ENOENT) { fputs(_("Samhain IPC not initialized.\n"), stderr); _exit(exit_err); } else if (errno == EACCES) fputs(_("No permission to access Samhain IPC.\n"), stderr); _exit(exit_err); } } retry_msleep(0, 50); if (time_wait > 0) { signal(SIGALRM, alarm_handler); alarm(time_wait); } rc = SH_SEMAPHORE_LOCK(sem_id); if (rc == -1 && errno == EINTR) { if (alarm_triggered) { fputs(_("Timeout on wait.\n"), stderr); _exit(exit_time); } } else if (rc == -1) { if (errno == EACCES) fputs(_("No permission to access Samhain IPC.\n"), stderr); else perror(_("semop")); _exit(exit_err); } rc = sem_get(sem_id, 1); if (rc == 0) _exit(exit_ok); else if (rc == SH_SEMVMX) fprintf(stdout, _("%d or more issues reported\n"), rc); else fprintf(stdout, _("%d issues reported\n"), rc); _exit(exit_fail); } #else void sh_sem_open() { return; } void sh_sem_trylock() { return; } void sh_sem_lock() { return; } void sh_sem_unlock(long val) { (void) val; return; } void sh_sem_close() { return; } int sh_sem_wait(const char * wait) { (void) wait; fputs(_("Function not implemented (OS does not support SysV semaphores).\n"), stderr); exit(exit_err); } #endif /* defined(HAVE_SYS_SEM_H) && defined(HAVE_UNISTD_H) */