22
22
#include <sys/types.h>
23
23
#include <sys/stat.h>
24
24
#include <sys/syscall.h>
25
#include <sys/socket.h>
27
28
#include <limits.h>
28
29
#include <stdarg.h>
34
/* some non-Linux systems do not define a static value */
36
# define PATH_MAX 4096
30
39
#define symbol_version(real, name, version) \
31
40
__asm__ (".symver " #real "," #name "@" #version)
32
41
#define default_symbol_version(real, name, version) \
33
42
__asm__ (".symver " #real "," #name "@@" #version)
35
static int setprocattr(const char *path, const char *buf, int len)
38
int fd, ret, ctlerr = 0;
45
* aa_find_mountpoint - find where the apparmor interface filesystem is mounted
46
* @mnt: returns buffer with the mountpoint string
48
* Returns: 0 on success else -1 on error
50
* NOTE: this function only supports versions of apparmor using securityfs
52
int aa_find_mountpoint(char **mnt)
64
mntfile = setmntent("/proc/mounts", "r");
68
while ((mntpt = getmntent(mntfile))) {
69
char *proposed = NULL;
70
if (strcmp(mntpt->mnt_type, "securityfs") != 0)
73
if (asprintf(&proposed, "%s/apparmor", mntpt->mnt_dir) < 0)
77
if (stat(proposed, &statbuf) == 0) {
91
* aa_is_enabled - determine if apparmor is enabled
93
* Returns: 1 if enabled else reason it is not, or 0 on error
95
* ENOSYS - no indication apparmor is present in the system
96
* ENOENT - enabled but interface could not be found
97
* ECANCELED - disabled at boot
98
* ENOMEM - out of memory
100
int aa_is_enabled(void)
102
int serrno, fd, rc, size;
106
/* if the interface mountpoint is available apparmor is enabled */
107
rc = aa_find_mountpoint(&mnt);
113
/* determine why the interface mountpoint isn't available */
114
fd = open("/sys/module/apparmor/parameters/enabled", O_RDONLY);
121
size = read(fd, &buffer, 2);
127
if (buffer[0] == 'Y')
135
static inline pid_t aa_gettid(void)
138
return syscall(SYS_gettid);
144
static char *procattr_path(pid_t pid, const char *attr)
147
if (asprintf(&path, "/proc/%d/attr/%s", pid, attr) > 0)
153
* aa_getprocattr_raw - get the contents of @attr for @tid into @buf
154
* @tid: tid of task to query
155
* @attr: which /proc/<tid>/attr/<attr> to query
156
* @buf: buffer to store the result in
157
* @len: size of the buffer
158
* @mode: if set will point to mode string within buffer if it is present
160
* Returns: size of data read or -1 on error, and sets errno
162
int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
170
if (!buf || len <= 0) {
175
tmp = procattr_path(tid, attr);
179
fd = open(tmp, O_RDONLY);
187
ret = read(fd, tmp, len);
208
} else if (size > 0 && buf[size - 1] != 0) {
209
/* check for null termination */
210
if (buf[size - 1] == '\n') {
212
} else if (len == 0) {
221
* now separate the mode. If we don't find it just
226
if (strcmp(buf, "unconfined") != 0 &&
227
size > 4 && buf[size - 2] == ')') {
230
!(buf[pos] == ' ' && buf[pos + 1] == '('))
233
buf[pos] = 0; /* overwrite ' ' */
234
buf[size - 2] = 0; /* overwrite trailing ) */
236
*mode = &buf[pos + 2]; /* skip '(' */
248
#define INITIAL_GUESS_SIZE 128
251
* aa_getprocattr - get the contents of @attr for @tid into @buf
252
* @tid: tid of task to query
253
* @attr: which /proc/<tid>/attr/<attr> to query
254
* @buf: allocated buffer the result is stored in
255
* @mode: if set will point to mode string within buffer if it is present
257
* Returns: size of data read or -1 on error, and sets errno
259
int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode)
261
int rc, size = INITIAL_GUESS_SIZE/2;
271
buffer = realloc(buffer, size);
274
memset(buffer, 0, size);
276
rc = aa_getprocattr_raw(tid, attr, buffer, size, mode);
277
} while (rc == -1 && errno == ERANGE);
288
static int setprocattr(pid_t tid, const char *attr, const char *buf, int len)
40
pid_t tid = syscall(SYS_gettid);
47
ctlerr = asprintf(&ctl, path, tid);
299
ctl = procattr_path(tid, attr);
52
303
fd = open(ctl, O_WRONLY);
252
503
return aa_change_hatv(argv, token);
507
* aa_gettaskcon - get the confinement for task @target in an allocated buffer
508
* @target: task to query
509
* @con: pointer to returned buffer with the confinement string
510
* @mode: if provided will point to the mode string in @con if present
512
* Returns: length of confinement data or -1 on error and sets errno
514
* Guarentees that @con and @mode are null terminated. The length returned
515
* is for all data including both @con and @mode, and maybe > than strlen(@con)
516
* even if @mode is NULL
518
* Caller is responsible for freeing the buffer returned in @con. @mode is
519
* always contained within @con's buffer and so NEVER do free(@mode)
521
int aa_gettaskcon(pid_t target, char **con, char **mode)
523
return aa_getprocattr(target, "current", con, mode);
527
* aa_getcon - get the confinement for current task in an allocated buffer
528
* @con: pointer to return buffer with the confinement if successful
529
* @mode: if provided will point to the mode string in @con if present
531
* Returns: length of confinement data or -1 on error and sets errno
533
* Guarentees that @con and @mode are null terminated. The length returned
534
* is for all data including both @con and @mode, and may > than strlen(@con)
535
* even if @mode is NULL
537
* Caller is responsible for freeing the buffer returned in @con. @mode is
538
* always contained within @con's buffer and so NEVER do free(@mode)
540
int aa_getcon(char **con, char **mode)
542
return aa_gettaskcon(aa_gettid(), con, mode);
547
#define SO_PEERSEC 31
551
* aa_getpeercon_raw - get the confinement of the socket's peer (other end)
552
* @fd: socket to get peer confinement for
553
* @con: pointer to buffer to store confinement string
554
* @size: initially contains size of the buffer, returns size of data read
556
* Returns: length of confinement data including null termination or -1 on error
557
* if errno == ERANGE then @size will hold the size needed
559
int aa_getpeercon_raw(int fd, char *buffer, int *size)
561
socklen_t optlen = *size;
564
if (optlen <= 0 || buffer == NULL) {
569
rc = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buffer, &optlen);
570
if (rc == -1 || optlen <= 0)
573
/* check for null termination */
574
if (buffer[optlen - 1] != 0) {
575
if (optlen < *size) {
579
/* buffer needs to be bigger by 1 */
591
* aa_getpeercon - get the confinement of the socket's peer (other end)
592
* @fd: socket to get peer confinement for
593
* @con: pointer to allocated buffer with the confinement string
595
* Returns: length of confinement data including null termination or -1 on error
597
* Caller is responsible for freeing the buffer returned.
599
int aa_getpeercon(int fd, char **con)
601
int rc, size = INITIAL_GUESS_SIZE;
610
buffer = realloc(buffer, size);
613
memset(buffer, 0, size);
615
rc = aa_getpeercon_raw(fd, buffer, &size);
616
} while (rc == -1 && errno == ERANGE);