Open-Source-Software-Entwicklung und Downloads

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 581 - (hide annotations) (download) (as text)
Tue Oct 16 08:00:21 2007 UTC (16 years, 7 months ago) by kumaneko
Original Path: trunk/1.5.x/ccs-patch/fs/tomoyo_capability.c
File MIME type: text/x-csrc
File size: 9640 byte(s)
Add environment variable checking function
1 kumaneko 111 /*
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 kumaneko 581 * Version: 1.5.1-pre 2007/10/16
9 kumaneko 111 *
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 kumaneko 141 [TOMOYO_SYS_PIVOT_ROOT] = { "SYS_PIVOT_ROOT", 0, "sys_pivot_root()" },
60 kumaneko 111 };
61    
62 kumaneko 214 struct profile {
63 kumaneko 111 unsigned char value[TOMOYO_MAX_CAPABILITY_INDEX];
64 kumaneko 214 };
65 kumaneko 111
66 kumaneko 214 static struct profile *profile_ptr[MAX_PROFILES];
67 kumaneko 111
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 kumaneko 121 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 kumaneko 111 }
90    
91     /* Check whether the given capability control is enforce mode. */
92 kumaneko 512 static u8 CheckCapabilityEnforce(const unsigned int index)
93 kumaneko 111 {
94     return CheckCapabilityFlags(index) == 3;
95     }
96    
97 kumaneko 461 /* Check whether the given capability control is learning mode. */
98 kumaneko 512 static u8 CheckCapabilityAccept(const unsigned int index, struct domain_info * const domain)
99 kumaneko 111 {
100 kumaneko 512 if (CheckCapabilityFlags(index) != 1) return 0;
101     return CheckDomainQuota(domain);
102 kumaneko 111 }
103    
104 kumaneko 214 static struct profile *FindOrAssignNewProfile(const unsigned int profile)
105 kumaneko 111 {
106     static DECLARE_MUTEX(profile_lock);
107 kumaneko 214 struct profile *ptr = NULL;
108 kumaneko 111 down(&profile_lock);
109     if (profile < MAX_PROFILES && (ptr = profile_ptr[profile]) == NULL) {
110 kumaneko 214 if ((ptr = alloc_element(sizeof(*ptr))) != NULL) {
111 kumaneko 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 kumaneko 214 struct profile *ptr = FindOrAssignNewProfile(profile);
125 kumaneko 111 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 kumaneko 214 int ReadCapabilityStatus(struct io_buffer *head)
136 kumaneko 111 {
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 kumaneko 214 const struct profile *profile = profile_ptr[i];
141 kumaneko 111 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 kumaneko 512 static int AuditCapabilityLog(const unsigned int capability, const u8 is_granted)
151 kumaneko 111 {
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 kumaneko 514 static int AddCapabilityACL(const unsigned int capability, struct domain_info *domain, const struct condition_list *condition, const u8 is_delete)
163 kumaneko 111 {
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 kumaneko 514 if (!is_delete) {
170 kumaneko 111 if ((ptr = domain->first_acl_ptr) == NULL) goto first_entry;
171     while (1) {
172 kumaneko 328 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 kumaneko 111 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 kumaneko 214 if ((new_ptr = alloc_element(sizeof(*new_ptr))) == NULL) break;
186 kumaneko 111 new_ptr->head.type = TYPE_CAPABILITY_ACL;
187 kumaneko 328 new_ptr->capability = hash;
188 kumaneko 111 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 kumaneko 328 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 kumaneko 111 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 kumaneko 512 const u8 is_enforce = CheckCapabilityEnforce(capability);
210 kumaneko 111 const u16 hash = capability;
211     if (!CheckCapabilityFlags(capability)) return 0;
212     for (ptr = domain->first_acl_ptr; ptr; ptr = ptr->next) {
213 kumaneko 328 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 kumaneko 111 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 kumaneko 514 if (CheckCapabilityAccept(capability, domain)) AddCapabilityACL(capability, domain, NULL, 0);
224 kumaneko 111 return 0;
225     }
226 kumaneko 223 EXPORT_SYMBOL(CheckCapabilityACL);
227 kumaneko 111
228 kumaneko 581 int AddCapabilityPolicy(char *data, struct domain_info *domain, const struct condition_list *condition, const u8 is_delete)
229 kumaneko 111 {
230     unsigned int capability;
231     for (capability = 0; capability < TOMOYO_MAX_CAPABILITY_INDEX; capability++) {
232     if (strcmp(data, capability_control_array[capability].keyword) == 0) {
233 kumaneko 514 return AddCapabilityACL(capability, domain, condition, is_delete);
234 kumaneko 111 }
235     }
236     return -EINVAL;
237     }
238    
239     /***** TOMOYO Linux end. *****/

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