chiark / gitweb /
udev_device_init() remove statically allocated device support
[elogind.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 "config.h"
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <stddef.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <fcntl.h>
27 #include <ctype.h>
28 #include <limits.h>
29 #include <errno.h>
30 #include <sys/stat.h>
31 #include <selinux/selinux.h>
32
33 #include "udev.h"
34 #include "udev_selinux.h"
35
36 static security_context_t prev_scontext = NULL;
37
38 static int is_selinux_running(void)
39 {
40         static int selinux_enabled = -1;
41
42         if (selinux_enabled == -1) 
43                 selinux_enabled = (is_selinux_enabled() > 0);
44
45         dbg("selinux=%i\n", selinux_enabled);
46         return selinux_enabled;
47 }
48
49 static char *get_media(const char *devname, int mode)
50 {
51         FILE *fp;
52         char procfile[PATH_MAX];
53         char mediabuf[256];
54         int size;
55         char *media = NULL;
56
57         if (!(mode & S_IFBLK))
58                 return NULL;
59
60         snprintf(procfile, PATH_MAX, "/proc/ide/%s/media", devname);
61         procfile[PATH_MAX-1] = '\0';
62
63         fp = fopen(procfile, "r");
64         if (!fp)
65                 goto out;
66
67         if (fgets(mediabuf, sizeof(mediabuf), fp) == NULL)
68                 goto close_out;
69
70         size = strlen(mediabuf);
71         while (size-- > 0) {
72                 if (isspace(mediabuf[size])) {
73                         mediabuf[size] = '\0';
74                 } else {
75                         break;
76                 }
77         }
78
79         media = strdup(mediabuf);
80         info("selinux_get_media(%s)='%s'\n", devname, media);
81
82 close_out:
83         fclose(fp);
84 out:
85         return media;
86 }
87
88 void selinux_setfilecon(const char *file, const char *devname, unsigned int mode)
89 {
90         if (is_selinux_running()) {
91                 security_context_t scontext = NULL;
92                 char *media;
93                 int ret = -1;
94
95                 if (devname) {
96                         media = get_media(devname, mode);
97                         if (media) {
98                                 ret = matchmediacon(media, &scontext);
99                                 free(media);
100                         }
101                 }
102
103                 if (ret < 0)
104                         if (matchpathcon(file, mode, &scontext) < 0) {
105                                 err("matchpathcon(%s) failed\n", file);
106                                 return;
107                         } 
108
109                 if (lsetfilecon(file, scontext) < 0)
110                         err("setfilecon %s failed: %s\n", file, strerror(errno));
111
112                 freecon(scontext);
113         }
114 }
115
116 void selinux_setfscreatecon(const char *file, const char *devname, unsigned int mode)
117 {
118         if (is_selinux_running()) {
119                 security_context_t scontext = NULL;
120                 char *media;
121                 int ret = -1;
122
123                 if (devname) {
124                         media = get_media(devname, mode);
125                         if (media) {
126                                 ret = matchmediacon(media, &scontext);
127                                 free(media);
128                         }
129                 }
130
131                 if (ret < 0)
132                         if (matchpathcon(file, mode, &scontext) < 0) {
133                                 err("matchpathcon(%s) failed\n", file);
134                                 return;
135                         }
136
137                 if (setfscreatecon(scontext) < 0)
138                         err("setfscreatecon %s failed: %s\n", file, strerror(errno));
139
140                 freecon(scontext);
141         }
142 }
143
144 void selinux_resetfscreatecon(void)
145 {
146         if (is_selinux_running()) {
147                 if (setfscreatecon(prev_scontext) < 0)
148                         err("setfscreatecon failed: %s\n", strerror(errno));
149         }
150 }
151
152 void selinux_init(void)
153 {
154         /*
155          * record the present security context, for file-creation
156          * restoration creation purposes.
157          */
158         if (is_selinux_running()) {
159                 if (!udev_root[0])
160                         err("selinux_init: udev_root not set\n");
161                 matchpathcon_init_prefix(NULL, udev_root);
162                 if (getfscreatecon(&prev_scontext) < 0) {
163                         err("getfscreatecon failed\n");
164                         prev_scontext = NULL;
165                 }
166         }
167 }
168
169 void selinux_exit(void)
170 {
171         if (is_selinux_running() && prev_scontext) {
172                 freecon(prev_scontext);
173                 prev_scontext = NULL;
174         }
175 }