#include <sys/syscall.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include "selinux_internal.h" #include "policy.h" #ifdef HOST static pid_t gettid(void) { return syscall(__NR_gettid); } #endif static int openattr(pid_t pid, const char *attr, int flags) { int fd, rc; char *path; pid_t tid; if (pid > 0) { rc = asprintf(&path, "/proc/%d/attr/%s", pid, attr); } else if (pid == 0) { rc = asprintf(&path, "/proc/thread-self/attr/%s", attr); if (rc < 0) return -1; fd = open(path, flags | O_CLOEXEC); if (fd >= 0 || errno != ENOENT) goto out; free(path); tid = gettid(); rc = asprintf(&path, "/proc/self/task/%d/attr/%s", tid, attr); } else { errno = EINVAL; return -1; } if (rc < 0) return -1; fd = open(path, flags | O_CLOEXEC); out: free(path); return fd; } static int getprocattrcon(char ** context, pid_t pid, const char *attr) { char *buf; size_t size; int fd; ssize_t ret; int errno_hold; fd = openattr(pid, attr, O_RDONLY); if (fd < 0) return -1; size = selinux_page_size; buf = malloc(size); if (!buf) { ret = -1; goto out; } memset(buf, 0, size); do { ret = read(fd, buf, size - 1); } while (ret < 0 && errno == EINTR); if (ret < 0) goto out2; if (ret == 0) { *context = NULL; goto out2; } *context = strdup(buf); if (!(*context)) { ret = -1; goto out2; } ret = 0; out2: free(buf); out: errno_hold = errno; close(fd); errno = errno_hold; return ret; } static int setprocattrcon(const char * context, pid_t pid, const char *attr) { int fd; ssize_t ret; int errno_hold; fd = openattr(pid, attr, O_RDWR); if (fd < 0) return -1; if (context) do { ret = write(fd, context, strlen(context) + 1); } while (ret < 0 && errno == EINTR); else do { ret = write(fd, NULL, 0); /* clear */ } while (ret < 0 && errno == EINTR); errno_hold = errno; close(fd); errno = errno_hold; if (ret < 0) return -1; else return 0; } #define getselfattr_def(fn, attr) \ int get##fn(char **c) \ { \ return getprocattrcon(c, 0, #attr); \ } #define setselfattr_def(fn, attr) \ int set##fn(const char * c) \ { \ return setprocattrcon(c, 0, #attr); \ } #define all_selfattr_def(fn, attr) \ getselfattr_def(fn, attr) \ setselfattr_def(fn, attr) #define getpidattr_def(fn, attr) \ int get##fn(pid_t pid, char **c) \ { \ if (pid <= 0) { \ errno = EINVAL; \ return -1; \ } else { \ return getprocattrcon(c, pid, #attr); \ } \ } all_selfattr_def(con, current) getpidattr_def(pidcon, current) getselfattr_def(prevcon, prev) all_selfattr_def(execcon, exec) all_selfattr_def(fscreatecon, fscreate) all_selfattr_def(sockcreatecon, sockcreate) all_selfattr_def(keycreatecon, keycreate) hidden_def(getcon_raw) hidden_def(getcon) hidden_def(getexeccon_raw) hidden_def(getfilecon_raw) hidden_def(getfilecon) hidden_def(getfscreatecon_raw) hidden_def(getkeycreatecon_raw) hidden_def(getpeercon_raw) hidden_def(getpidcon_raw) hidden_def(getprevcon_raw) hidden_def(getprevcon) hidden_def(getsockcreatecon_raw) hidden_def(setcon_raw) hidden_def(setexeccon_raw) hidden_def(setexeccon) hidden_def(setfilecon_raw) hidden_def(setfscreatecon_raw) hidden_def(setkeycreatecon_raw) hidden_def(setsockcreatecon_raw)