chiark / gitweb /
remove old error message
[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 <libgen.h>
28 #include <errno.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", 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", 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                 media = get_media(devname, mode);
122                 if (media) {
123                         ret = matchmediacon(media, &scontext);
124                         free(media);
125                 }
126
127                 if (ret < 0)
128                         if (matchpathcon(file, mode, &scontext) < 0) {
129                                 err("matchpathcon(%s) failed\n", file);
130                                 return;
131                         }
132
133                 if (setfscreatecon(scontext) < 0)
134                         err("setfscreatecon %s failed: %s", file, strerror(errno));
135
136                 freecon(scontext);
137         }
138 }
139
140 void selinux_resetfscreatecon(void)
141 {
142         if (is_selinux_running()) {
143                 if (setfscreatecon(prev_scontext) < 0)
144                         err("setfscreatecon failed: %s", strerror(errno));
145         }
146 }
147
148 void selinux_init(void)
149 {
150         /*
151          * record the present security context, for file-creation
152          * restoration creation purposes.
153          */
154         if (is_selinux_running()) {
155                 matchpathcon_init_prefix(NULL, udev_root);
156                 if (getfscreatecon(&prev_scontext) < 0) {
157                         err("getfscreatecon failed\n");
158                         prev_scontext = NULL;
159                 }
160         }
161 }
162
163 void selinux_exit(void)
164 {
165         if (is_selinux_running() && prev_scontext) {
166                 freecon(prev_scontext);
167                 prev_scontext = NULL;
168         }
169 }