chiark / gitweb /
do not touch node ownership and permissions, if already correct
[elogind.git] / 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 }