]> git.ipfire.org Git - thirdparty/systemd.git/blob - udev/udev_selinux.c
use proper directory lib/lib64 for libvolume_id
[thirdparty/systemd.git] / udev / udev_selinux.c
1 /*
2 * Copyright (C) 2004 Daniel Walsh
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 *
17 */
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <stddef.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <fcntl.h>
25 #include <ctype.h>
26 #include <limits.h>
27 #include <errno.h>
28 #include <sys/stat.h>
29 #include <selinux/selinux.h>
30
31 #include "udev.h"
32 #include "udev_selinux.h"
33
34 static security_context_t prev_scontext = NULL;
35
36 static int is_selinux_running(void)
37 {
38 static int selinux_enabled = -1;
39
40 if (selinux_enabled == -1)
41 selinux_enabled = (is_selinux_enabled() > 0);
42
43 dbg("selinux=%i\n", selinux_enabled);
44 return selinux_enabled;
45 }
46
47 static char *get_media(const char *devname, int mode)
48 {
49 FILE *fp;
50 char procfile[PATH_MAX];
51 char mediabuf[256];
52 int size;
53 char *media = NULL;
54
55 if (!(mode & S_IFBLK))
56 return NULL;
57
58 snprintf(procfile, PATH_MAX, "/proc/ide/%s/media", devname);
59 procfile[PATH_MAX-1] = '\0';
60
61 fp = fopen(procfile, "r");
62 if (!fp)
63 goto out;
64
65 if (fgets(mediabuf, sizeof(mediabuf), fp) == NULL)
66 goto close_out;
67
68 size = strlen(mediabuf);
69 while (size-- > 0) {
70 if (isspace(mediabuf[size])) {
71 mediabuf[size] = '\0';
72 } else {
73 break;
74 }
75 }
76
77 media = strdup(mediabuf);
78 info("selinux_get_media(%s)='%s'\n", devname, media);
79
80 close_out:
81 fclose(fp);
82 out:
83 return media;
84 }
85
86 void selinux_setfilecon(const char *file, const char *devname, unsigned int mode)
87 {
88 if (is_selinux_running()) {
89 security_context_t scontext = NULL;
90 char *media;
91 int ret = -1;
92
93 if (devname) {
94 media = get_media(devname, mode);
95 if (media) {
96 ret = matchmediacon(media, &scontext);
97 free(media);
98 }
99 }
100
101 if (ret < 0)
102 if (matchpathcon(file, mode, &scontext) < 0) {
103 err("matchpathcon(%s) failed\n", file);
104 return;
105 }
106
107 if (lsetfilecon(file, scontext) < 0)
108 err("setfilecon %s failed: %s\n", file, strerror(errno));
109
110 freecon(scontext);
111 }
112 }
113
114 void selinux_setfscreatecon(const char *file, const char *devname, unsigned int mode)
115 {
116 if (is_selinux_running()) {
117 security_context_t scontext = NULL;
118 char *media;
119 int ret = -1;
120
121 if (devname) {
122 media = get_media(devname, mode);
123 if (media) {
124 ret = matchmediacon(media, &scontext);
125 free(media);
126 }
127 }
128
129 if (ret < 0)
130 if (matchpathcon(file, mode, &scontext) < 0) {
131 err("matchpathcon(%s) failed\n", file);
132 return;
133 }
134
135 if (setfscreatecon(scontext) < 0)
136 err("setfscreatecon %s failed: %s\n", file, strerror(errno));
137
138 freecon(scontext);
139 }
140 }
141
142 void selinux_resetfscreatecon(void)
143 {
144 if (is_selinux_running()) {
145 if (setfscreatecon(prev_scontext) < 0)
146 err("setfscreatecon failed: %s\n", strerror(errno));
147 }
148 }
149
150 void selinux_init(void)
151 {
152 /*
153 * record the present security context, for file-creation
154 * restoration creation purposes.
155 */
156 if (is_selinux_running()) {
157 if (!udev_root[0])
158 err("selinux_init: udev_root not set\n");
159 matchpathcon_init_prefix(NULL, udev_root);
160 if (getfscreatecon(&prev_scontext) < 0) {
161 err("getfscreatecon failed\n");
162 prev_scontext = NULL;
163 }
164 }
165 }
166
167 void selinux_exit(void)
168 {
169 if (is_selinux_running() && prev_scontext) {
170 freecon(prev_scontext);
171 prev_scontext = NULL;
172 }
173 }