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