Open-Source-Software-Entwicklung und Downloads

Browse Subversion Repository

Contents of /trunk/1.6.x/ccs-patch/fs/tomoyo_capability.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 514 - (show annotations) (download) (as text)
Fri Sep 28 05:08:39 2007 UTC (16 years, 8 months ago) by kumaneko
Original Path: trunk/1.5.x/ccs-patch/fs/tomoyo_capability.c
File MIME type: text/x-csrc
File size: 9760 byte(s)


1 /*
2 * fs/tomoyo_capability.c
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2007 NTT DATA CORPORATION
7 *
8 * Version: 1.5.0 2007/09/20
9 *
10 * This file is applicable to both 2.4.30 and 2.6.11 and later.
11 * See README.ccs for ChangeLog.
12 *
13 */
14 /***** TOMOYO Linux start. *****/
15
16 #include <linux/ccs_common.h>
17 #include <linux/tomoyo.h>
18 #include <linux/realpath.h>
19
20 /************************* VARIABLES *************************/
21
22 extern struct semaphore domain_acl_lock;
23 extern int sbin_init_started;
24
25 static struct {
26 const char *keyword;
27 unsigned int current_value;
28 const char *capability_name;
29 } capability_control_array[TOMOYO_MAX_CAPABILITY_INDEX] = { /* domain_policy.txt */
30 [TOMOYO_INET_STREAM_SOCKET_CREATE] = { "inet_tcp_create", 0, "socket(PF_INET, SOCK_STREAM)" },
31 [TOMOYO_INET_STREAM_SOCKET_LISTEN] = { "inet_tcp_listen", 0, "listen(PF_INET, SOCK_STREAM)" },
32 [TOMOYO_INET_STREAM_SOCKET_CONNECT] = { "inet_tcp_connect", 0, "connect(PF_INET, SOCK_STREAM)" },
33 [TOMOYO_USE_INET_DGRAM_SOCKET] = { "use_inet_udp", 0, "socket(PF_INET, SOCK_DGRAM)" },
34 [TOMOYO_USE_INET_RAW_SOCKET] = { "use_inet_ip", 0, "socket(PF_INET, SOCK_RAW)" },
35 [TOMOYO_USE_ROUTE_SOCKET] = { "use_route", 0, "socket(PF_ROUTE)" },
36 [TOMOYO_USE_PACKET_SOCKET] = { "use_packet", 0, "socket(PF_PACKET)" },
37 [TOMOYO_SYS_MOUNT] = { "SYS_MOUNT", 0, "sys_mount()" },
38 [TOMOYO_SYS_UMOUNT] = { "SYS_UMOUNT", 0, "sys_umount()" },
39 [TOMOYO_SYS_REBOOT] = { "SYS_REBOOT", 0, "sys_reboot()" },
40 [TOMOYO_SYS_CHROOT] = { "SYS_CHROOT", 0, "sys_chroot()" },
41 [TOMOYO_SYS_KILL] = { "SYS_KILL", 0, "sys_kill()" },
42 [TOMOYO_SYS_VHANGUP] = { "SYS_VHANGUP", 0, "sys_vhangup()" },
43 [TOMOYO_SYS_SETTIME] = { "SYS_TIME", 0, "sys_settimeofday()" },
44 [TOMOYO_SYS_NICE] = { "SYS_NICE", 0, "sys_nice()" },
45 [TOMOYO_SYS_SETHOSTNAME] = { "SYS_SETHOSTNAME", 0, "sys_sethostname()" },
46 [TOMOYO_USE_KERNEL_MODULE] = { "use_kernel_module", 0, "kernel_module" },
47 [TOMOYO_CREATE_FIFO] = { "create_fifo", 0, "mknod(FIFO)" },
48 [TOMOYO_CREATE_BLOCK_DEV] = { "create_block_dev", 0, "mknod(BDEV)" },
49 [TOMOYO_CREATE_CHAR_DEV] = { "create_char_dev", 0, "mknod(CDEV)" },
50 [TOMOYO_CREATE_UNIX_SOCKET] = { "create_unix_socket", 0, "mknod(SOCKET)" },
51 [TOMOYO_SYS_LINK] = { "SYS_LINK", 0, "sys_link()" },
52 [TOMOYO_SYS_SYMLINK] = { "SYS_SYMLINK", 0, "sys_symlink()" },
53 [TOMOYO_SYS_RENAME] = { "SYS_RENAME", 0, "sys_rename()" },
54 [TOMOYO_SYS_UNLINK] = { "SYS_UNLINK", 0, "sys_unlink()" },
55 [TOMOYO_SYS_CHMOD] = { "SYS_CHMOD", 0, "sys_chmod()" },
56 [TOMOYO_SYS_CHOWN] = { "SYS_CHOWN", 0, "sys_chown()" },
57 [TOMOYO_SYS_IOCTL] = { "SYS_IOCTL", 0, "sys_ioctl()" },
58 [TOMOYO_SYS_KEXEC_LOAD] = { "SYS_KEXEC_LOAD", 0, "sys_kexec_load()" },
59 [TOMOYO_SYS_PIVOT_ROOT] = { "SYS_PIVOT_ROOT", 0, "sys_pivot_root()" },
60 };
61
62 struct profile {
63 unsigned char value[TOMOYO_MAX_CAPABILITY_INDEX];
64 };
65
66 static struct profile *profile_ptr[MAX_PROFILES];
67
68 /************************* UTILITY FUNCTIONS *************************/
69
70 const char *capability2keyword(const unsigned int capability)
71 {
72 return capability < TOMOYO_MAX_CAPABILITY_INDEX ? capability_control_array[capability].keyword : NULL;
73 }
74
75 static const char *capability2name(const unsigned int capability)
76 {
77 return capability < TOMOYO_MAX_CAPABILITY_INDEX ? capability_control_array[capability].capability_name : NULL;
78 }
79
80 /* Check whether the given capability control is enabled. */
81 static unsigned int CheckCapabilityFlags(const unsigned int index)
82 {
83 const u8 profile = current->domain_info->profile;
84 return sbin_init_started && index < TOMOYO_MAX_CAPABILITY_INDEX
85 #if MAX_PROFILES != 256
86 && profile < MAX_PROFILES
87 #endif
88 && profile_ptr[profile] ? profile_ptr[profile]->value[index] : 0;
89 }
90
91 /* Check whether the given capability control is enforce mode. */
92 static u8 CheckCapabilityEnforce(const unsigned int index)
93 {
94 return CheckCapabilityFlags(index) == 3;
95 }
96
97 /* Check whether the given capability control is learning mode. */
98 static u8 CheckCapabilityAccept(const unsigned int index, struct domain_info * const domain)
99 {
100 if (CheckCapabilityFlags(index) != 1) return 0;
101 return CheckDomainQuota(domain);
102 }
103
104 static struct profile *FindOrAssignNewProfile(const unsigned int profile)
105 {
106 static DECLARE_MUTEX(profile_lock);
107 struct profile *ptr = NULL;
108 down(&profile_lock);
109 if (profile < MAX_PROFILES && (ptr = profile_ptr[profile]) == NULL) {
110 if ((ptr = alloc_element(sizeof(*ptr))) != NULL) {
111 int i;
112 for (i = 0; i < TOMOYO_MAX_CAPABILITY_INDEX; i++) ptr->value[i] = capability_control_array[i].current_value;
113 mb(); /* Instead of using spinlock. */
114 profile_ptr[profile] = ptr;
115 }
116 }
117 up(&profile_lock);
118 return ptr;
119 }
120
121 int SetCapabilityStatus(const char *data, unsigned int value, const unsigned int profile)
122 {
123 int i;
124 struct profile *ptr = FindOrAssignNewProfile(profile);
125 if (!ptr) return -EINVAL;
126 for (i = 0; i < TOMOYO_MAX_CAPABILITY_INDEX; i++) {
127 if (strcmp(data, capability_control_array[i].keyword)) continue;
128 if (value > 3) value = 3;
129 ptr->value[i] = value;
130 return 0;
131 }
132 return -EINVAL;
133 }
134
135 int ReadCapabilityStatus(struct io_buffer *head)
136 {
137 int step;
138 for (step = head->read_step; step < MAX_PROFILES * TOMOYO_MAX_CAPABILITY_INDEX; step++) {
139 const int i = step / TOMOYO_MAX_CAPABILITY_INDEX, j = step % TOMOYO_MAX_CAPABILITY_INDEX;
140 const struct profile *profile = profile_ptr[i];
141 head->read_step = step;
142 if (!profile) continue;
143 if (io_printf(head, "%u-" KEYWORD_MAC_FOR_CAPABILITY "%s=%u\n", i, capability_control_array[j].keyword, profile->value[j])) break;
144 }
145 return step < MAX_PROFILES * TOMOYO_MAX_CAPABILITY_INDEX ? -ENOMEM : 0;
146 }
147
148 /************************* AUDIT FUNCTIONS *************************/
149
150 static int AuditCapabilityLog(const unsigned int capability, const u8 is_granted)
151 {
152 char *buf;
153 int len = 64;
154 if (CanSaveAuditLog(is_granted) < 0) return -ENOMEM;
155 if ((buf = InitAuditLog(&len)) == NULL) return -ENOMEM;
156 snprintf(buf + strlen(buf), len - strlen(buf) - 1, KEYWORD_ALLOW_CAPABILITY "%s\n", capability2keyword(capability));
157 return WriteAuditLog(buf, is_granted);
158 }
159
160 /************************* CAPABILITY ACL HANDLER *************************/
161
162 static int AddCapabilityACL(const unsigned int capability, struct domain_info *domain, const struct condition_list *condition, const u8 is_delete)
163 {
164 struct acl_info *ptr;
165 int error = -ENOMEM;
166 const u16 hash = capability;
167 if (!domain) return -EINVAL;
168 down(&domain_acl_lock);
169 if (!is_delete) {
170 if ((ptr = domain->first_acl_ptr) == NULL) goto first_entry;
171 while (1) {
172 struct capability_acl_record *new_ptr = (struct capability_acl_record *) ptr;
173 if (ptr->type == TYPE_CAPABILITY_ACL && new_ptr->capability == hash && ptr->cond == condition) {
174 ptr->is_deleted = 0;
175 /* Found. Nothing to do. */
176 error = 0;
177 break;
178 }
179 if (ptr->next) {
180 ptr = ptr->next;
181 continue;
182 }
183 first_entry: ;
184 /* Not found. Append it to the tail. */
185 if ((new_ptr = alloc_element(sizeof(*new_ptr))) == NULL) break;
186 new_ptr->head.type = TYPE_CAPABILITY_ACL;
187 new_ptr->capability = hash;
188 new_ptr->head.cond = condition;
189 error = AddDomainACL(ptr, domain, (struct acl_info *) new_ptr);
190 break;
191 }
192 } else {
193 error = -ENOENT;
194 for (ptr = domain->first_acl_ptr; ptr; ptr = ptr->next) {
195 struct capability_acl_record *ptr2 = (struct capability_acl_record *) ptr;
196 if (ptr->type != TYPE_CAPABILITY_ACL || ptr->is_deleted || ptr2->capability != hash || ptr->cond != condition) continue;
197 error = DelDomainACL(ptr);
198 break;
199 }
200 }
201 up(&domain_acl_lock);
202 return error;
203 }
204
205 int CheckCapabilityACL(const unsigned int capability)
206 {
207 struct domain_info * const domain = current->domain_info;
208 struct acl_info *ptr;
209 const u8 is_enforce = CheckCapabilityEnforce(capability);
210 const u16 hash = capability;
211 if (!CheckCapabilityFlags(capability)) return 0;
212 for (ptr = domain->first_acl_ptr; ptr; ptr = ptr->next) {
213 struct capability_acl_record *ptr2 = (struct capability_acl_record *) ptr;
214 if (ptr->type != TYPE_CAPABILITY_ACL || ptr->is_deleted || ptr2->capability != hash || CheckCondition(ptr->cond, NULL)) continue;
215 AuditCapabilityLog(capability, 1);
216 return 0;
217 }
218 if (TomoyoVerboseMode()) {
219 printk("TOMOYO-%s: %s denied for %s\n", GetMSG(is_enforce), capability2name(capability), GetLastName(domain));
220 }
221 AuditCapabilityLog(capability, 0);
222 if (is_enforce) return CheckSupervisor("%s\n" KEYWORD_ALLOW_CAPABILITY "%s\n", domain->domainname->name, capability2keyword(capability));
223 if (CheckCapabilityAccept(capability, domain)) AddCapabilityACL(capability, domain, NULL, 0);
224 return 0;
225 }
226 EXPORT_SYMBOL(CheckCapabilityACL);
227
228 int AddCapabilityPolicy(char *data, struct domain_info *domain, const u8 is_delete)
229 {
230 unsigned int capability;
231 const struct condition_list *condition = NULL;
232 char *cp = FindConditionPart(data);
233 if (cp && (condition = FindOrAssignNewCondition(cp)) == NULL) return -EINVAL;
234 for (capability = 0; capability < TOMOYO_MAX_CAPABILITY_INDEX; capability++) {
235 if (strcmp(data, capability_control_array[capability].keyword) == 0) {
236 return AddCapabilityACL(capability, domain, condition, is_delete);
237 }
238 }
239 return -EINVAL;
240 }
241
242 /***** TOMOYO Linux end. *****/

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26