chiark / gitweb /
remove old symlinks before creating current ones
[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
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", 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                 media = get_media(devname, mode);
96                 if (media) {
97                         ret = matchmediacon(media, &scontext);
98                         free(media);
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 (setfilecon(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 }