chiark / gitweb /
libudev: queue - always rebuild queue file when nothing is queued anymore
[elogind.git] / libudev / libudev-selinux-private.c
1 /*
2  * libudev - interface to udev device information
3  *
4  * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <stddef.h>
15 #include <stdarg.h>
16 #include <unistd.h>
17 #include <selinux/selinux.h>
18
19 #include "libudev.h"
20 #include "libudev-private.h"
21
22 static int selinux_enabled;
23 security_context_t selinux_prev_scontext;
24
25 void udev_selinux_init(struct udev *udev)
26 {
27         /* record the present security context */
28         selinux_enabled = (is_selinux_enabled() > 0);
29         info(udev, "selinux=%i\n", selinux_enabled);
30         if (!selinux_enabled)
31                 return;
32         matchpathcon_init_prefix(NULL, udev_get_dev_path(udev));
33         if (getfscreatecon(&selinux_prev_scontext) < 0) {
34                 err(udev, "getfscreatecon failed\n");
35                 selinux_prev_scontext = NULL;
36         }
37 }
38
39 void udev_selinux_exit(struct udev *udev)
40 {
41         if (!selinux_enabled)
42                 return;
43         freecon(selinux_prev_scontext);
44         selinux_prev_scontext = NULL;
45 }
46
47 void udev_selinux_lsetfilecon(struct udev *udev, const char *file, unsigned int mode)
48 {
49         security_context_t scontext = NULL;
50
51         if (!selinux_enabled)
52                 return;
53         if (matchpathcon(file, mode, &scontext) < 0) {
54                 err(udev, "matchpathcon(%s) failed\n", file);
55                 return;
56         }
57         if (lsetfilecon(file, scontext) < 0)
58                 err(udev, "setfilecon %s failed: %m\n", file);
59         freecon(scontext);
60 }
61
62 void udev_selinux_setfscreatecon(struct udev *udev, const char *file, unsigned int mode)
63 {
64         security_context_t scontext = NULL;
65
66         if (!selinux_enabled)
67                 return;
68
69         if (matchpathcon(file, mode, &scontext) < 0) {
70                 err(udev, "matchpathcon(%s) failed\n", file);
71                 return;
72         }
73         if (setfscreatecon(scontext) < 0)
74                 err(udev, "setfscreatecon %s failed: %m\n", file);
75         freecon(scontext);
76 }
77
78 void udev_selinux_resetfscreatecon(struct udev *udev)
79 {
80         if (!selinux_enabled)
81                 return;
82         if (setfscreatecon(selinux_prev_scontext) < 0)
83                 err(udev, "setfscreatecon failed: %m\n");
84 }
85
86 void udev_selinux_setfscreateconat(struct udev *udev, int dfd, const char *file, unsigned int mode)
87 {
88         char filename[UTIL_PATH_SIZE];
89
90         if (!selinux_enabled)
91                 return;
92
93         /* resolve relative filename */
94         if (file[0] != '/') {
95                 char procfd[UTIL_PATH_SIZE];
96                 char target[UTIL_PATH_SIZE];
97                 ssize_t len;
98
99                 snprintf(procfd, sizeof(procfd), "/proc/%u/fd/%u", getpid(), dfd);
100                 len = readlink(procfd, target, sizeof(target));
101                 if (len <= 0 || len == sizeof(target))
102                         return;
103                 target[len] = '\0';
104
105                 util_strscpyl(filename, sizeof(filename), target, "/", file, NULL);
106                 file = filename;
107         }
108         udev_selinux_setfscreatecon(udev, file, mode);
109 }