1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * security/tomoyo/file.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2005-2011 NTT DATA CORPORATION
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include "common.h"
9*4882a593Smuzhiyun #include <linux/slab.h>
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun /*
12*4882a593Smuzhiyun * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index".
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
15*4882a593Smuzhiyun [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE,
16*4882a593Smuzhiyun [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN,
17*4882a593Smuzhiyun [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN,
18*4882a593Smuzhiyun [TOMOYO_TYPE_APPEND] = TOMOYO_MAC_FILE_OPEN,
19*4882a593Smuzhiyun [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK,
20*4882a593Smuzhiyun [TOMOYO_TYPE_GETATTR] = TOMOYO_MAC_FILE_GETATTR,
21*4882a593Smuzhiyun [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR,
22*4882a593Smuzhiyun [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE,
23*4882a593Smuzhiyun [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK,
24*4882a593Smuzhiyun [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT,
25*4882a593Smuzhiyun [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT,
26*4882a593Smuzhiyun };
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index".
30*4882a593Smuzhiyun */
31*4882a593Smuzhiyun const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
32*4882a593Smuzhiyun [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
33*4882a593Smuzhiyun [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR,
34*4882a593Smuzhiyun };
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /*
37*4882a593Smuzhiyun * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index".
38*4882a593Smuzhiyun */
39*4882a593Smuzhiyun const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
40*4882a593Smuzhiyun [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK,
41*4882a593Smuzhiyun [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME,
42*4882a593Smuzhiyun [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
43*4882a593Smuzhiyun };
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun /*
46*4882a593Smuzhiyun * Mapping table from "enum tomoyo_path_number_acl_index" to
47*4882a593Smuzhiyun * "enum tomoyo_mac_index".
48*4882a593Smuzhiyun */
49*4882a593Smuzhiyun const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
50*4882a593Smuzhiyun [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
51*4882a593Smuzhiyun [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR,
52*4882a593Smuzhiyun [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO,
53*4882a593Smuzhiyun [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK,
54*4882a593Smuzhiyun [TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL,
55*4882a593Smuzhiyun [TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD,
56*4882a593Smuzhiyun [TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN,
57*4882a593Smuzhiyun [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP,
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /**
61*4882a593Smuzhiyun * tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union".
62*4882a593Smuzhiyun *
63*4882a593Smuzhiyun * @ptr: Pointer to "struct tomoyo_name_union".
64*4882a593Smuzhiyun *
65*4882a593Smuzhiyun * Returns nothing.
66*4882a593Smuzhiyun */
tomoyo_put_name_union(struct tomoyo_name_union * ptr)67*4882a593Smuzhiyun void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun tomoyo_put_group(ptr->group);
70*4882a593Smuzhiyun tomoyo_put_name(ptr->filename);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun /**
74*4882a593Smuzhiyun * tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not.
75*4882a593Smuzhiyun *
76*4882a593Smuzhiyun * @name: Pointer to "struct tomoyo_path_info".
77*4882a593Smuzhiyun * @ptr: Pointer to "struct tomoyo_name_union".
78*4882a593Smuzhiyun *
79*4882a593Smuzhiyun * Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise.
80*4882a593Smuzhiyun */
81*4882a593Smuzhiyun const struct tomoyo_path_info *
tomoyo_compare_name_union(const struct tomoyo_path_info * name,const struct tomoyo_name_union * ptr)82*4882a593Smuzhiyun tomoyo_compare_name_union(const struct tomoyo_path_info *name,
83*4882a593Smuzhiyun const struct tomoyo_name_union *ptr)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun if (ptr->group)
86*4882a593Smuzhiyun return tomoyo_path_matches_group(name, ptr->group);
87*4882a593Smuzhiyun if (tomoyo_path_matches_pattern(name, ptr->filename))
88*4882a593Smuzhiyun return ptr->filename;
89*4882a593Smuzhiyun return NULL;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /**
93*4882a593Smuzhiyun * tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union".
94*4882a593Smuzhiyun *
95*4882a593Smuzhiyun * @ptr: Pointer to "struct tomoyo_number_union".
96*4882a593Smuzhiyun *
97*4882a593Smuzhiyun * Returns nothing.
98*4882a593Smuzhiyun */
tomoyo_put_number_union(struct tomoyo_number_union * ptr)99*4882a593Smuzhiyun void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun tomoyo_put_group(ptr->group);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun /**
105*4882a593Smuzhiyun * tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not.
106*4882a593Smuzhiyun *
107*4882a593Smuzhiyun * @value: Number to check.
108*4882a593Smuzhiyun * @ptr: Pointer to "struct tomoyo_number_union".
109*4882a593Smuzhiyun *
110*4882a593Smuzhiyun * Returns true if @value matches @ptr, false otherwise.
111*4882a593Smuzhiyun */
tomoyo_compare_number_union(const unsigned long value,const struct tomoyo_number_union * ptr)112*4882a593Smuzhiyun bool tomoyo_compare_number_union(const unsigned long value,
113*4882a593Smuzhiyun const struct tomoyo_number_union *ptr)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun if (ptr->group)
116*4882a593Smuzhiyun return tomoyo_number_matches_group(value, value, ptr->group);
117*4882a593Smuzhiyun return value >= ptr->values[0] && value <= ptr->values[1];
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun /**
121*4882a593Smuzhiyun * tomoyo_add_slash - Add trailing '/' if needed.
122*4882a593Smuzhiyun *
123*4882a593Smuzhiyun * @buf: Pointer to "struct tomoyo_path_info".
124*4882a593Smuzhiyun *
125*4882a593Smuzhiyun * Returns nothing.
126*4882a593Smuzhiyun *
127*4882a593Smuzhiyun * @buf must be generated by tomoyo_encode() because this function does not
128*4882a593Smuzhiyun * allocate memory for adding '/'.
129*4882a593Smuzhiyun */
tomoyo_add_slash(struct tomoyo_path_info * buf)130*4882a593Smuzhiyun static void tomoyo_add_slash(struct tomoyo_path_info *buf)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun if (buf->is_dir)
133*4882a593Smuzhiyun return;
134*4882a593Smuzhiyun /*
135*4882a593Smuzhiyun * This is OK because tomoyo_encode() reserves space for appending "/".
136*4882a593Smuzhiyun */
137*4882a593Smuzhiyun strcat((char *) buf->name, "/");
138*4882a593Smuzhiyun tomoyo_fill_path_info(buf);
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun /**
142*4882a593Smuzhiyun * tomoyo_get_realpath - Get realpath.
143*4882a593Smuzhiyun *
144*4882a593Smuzhiyun * @buf: Pointer to "struct tomoyo_path_info".
145*4882a593Smuzhiyun * @path: Pointer to "struct path".
146*4882a593Smuzhiyun *
147*4882a593Smuzhiyun * Returns true on success, false otherwise.
148*4882a593Smuzhiyun */
tomoyo_get_realpath(struct tomoyo_path_info * buf,const struct path * path)149*4882a593Smuzhiyun static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, const struct path *path)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun buf->name = tomoyo_realpath_from_path(path);
152*4882a593Smuzhiyun if (buf->name) {
153*4882a593Smuzhiyun tomoyo_fill_path_info(buf);
154*4882a593Smuzhiyun return true;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun return false;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun /**
160*4882a593Smuzhiyun * tomoyo_audit_path_log - Audit path request log.
161*4882a593Smuzhiyun *
162*4882a593Smuzhiyun * @r: Pointer to "struct tomoyo_request_info".
163*4882a593Smuzhiyun *
164*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
165*4882a593Smuzhiyun */
tomoyo_audit_path_log(struct tomoyo_request_info * r)166*4882a593Smuzhiyun static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun return tomoyo_supervisor(r, "file %s %s\n", tomoyo_path_keyword
169*4882a593Smuzhiyun [r->param.path.operation],
170*4882a593Smuzhiyun r->param.path.filename->name);
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun /**
174*4882a593Smuzhiyun * tomoyo_audit_path2_log - Audit path/path request log.
175*4882a593Smuzhiyun *
176*4882a593Smuzhiyun * @r: Pointer to "struct tomoyo_request_info".
177*4882a593Smuzhiyun *
178*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
179*4882a593Smuzhiyun */
tomoyo_audit_path2_log(struct tomoyo_request_info * r)180*4882a593Smuzhiyun static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
183*4882a593Smuzhiyun [tomoyo_pp2mac[r->param.path2.operation]],
184*4882a593Smuzhiyun r->param.path2.filename1->name,
185*4882a593Smuzhiyun r->param.path2.filename2->name);
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /**
189*4882a593Smuzhiyun * tomoyo_audit_mkdev_log - Audit path/number/number/number request log.
190*4882a593Smuzhiyun *
191*4882a593Smuzhiyun * @r: Pointer to "struct tomoyo_request_info".
192*4882a593Smuzhiyun *
193*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
194*4882a593Smuzhiyun */
tomoyo_audit_mkdev_log(struct tomoyo_request_info * r)195*4882a593Smuzhiyun static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n",
198*4882a593Smuzhiyun tomoyo_mac_keywords
199*4882a593Smuzhiyun [tomoyo_pnnn2mac[r->param.mkdev.operation]],
200*4882a593Smuzhiyun r->param.mkdev.filename->name,
201*4882a593Smuzhiyun r->param.mkdev.mode, r->param.mkdev.major,
202*4882a593Smuzhiyun r->param.mkdev.minor);
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun /**
206*4882a593Smuzhiyun * tomoyo_audit_path_number_log - Audit path/number request log.
207*4882a593Smuzhiyun *
208*4882a593Smuzhiyun * @r: Pointer to "struct tomoyo_request_info".
209*4882a593Smuzhiyun *
210*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
211*4882a593Smuzhiyun */
tomoyo_audit_path_number_log(struct tomoyo_request_info * r)212*4882a593Smuzhiyun static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun const u8 type = r->param.path_number.operation;
215*4882a593Smuzhiyun u8 radix;
216*4882a593Smuzhiyun char buffer[64];
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun switch (type) {
219*4882a593Smuzhiyun case TOMOYO_TYPE_CREATE:
220*4882a593Smuzhiyun case TOMOYO_TYPE_MKDIR:
221*4882a593Smuzhiyun case TOMOYO_TYPE_MKFIFO:
222*4882a593Smuzhiyun case TOMOYO_TYPE_MKSOCK:
223*4882a593Smuzhiyun case TOMOYO_TYPE_CHMOD:
224*4882a593Smuzhiyun radix = TOMOYO_VALUE_TYPE_OCTAL;
225*4882a593Smuzhiyun break;
226*4882a593Smuzhiyun case TOMOYO_TYPE_IOCTL:
227*4882a593Smuzhiyun radix = TOMOYO_VALUE_TYPE_HEXADECIMAL;
228*4882a593Smuzhiyun break;
229*4882a593Smuzhiyun default:
230*4882a593Smuzhiyun radix = TOMOYO_VALUE_TYPE_DECIMAL;
231*4882a593Smuzhiyun break;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
234*4882a593Smuzhiyun radix);
235*4882a593Smuzhiyun return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
236*4882a593Smuzhiyun [tomoyo_pn2mac[type]],
237*4882a593Smuzhiyun r->param.path_number.filename->name, buffer);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun /**
241*4882a593Smuzhiyun * tomoyo_check_path_acl - Check permission for path operation.
242*4882a593Smuzhiyun *
243*4882a593Smuzhiyun * @r: Pointer to "struct tomoyo_request_info".
244*4882a593Smuzhiyun * @ptr: Pointer to "struct tomoyo_acl_info".
245*4882a593Smuzhiyun *
246*4882a593Smuzhiyun * Returns true if granted, false otherwise.
247*4882a593Smuzhiyun *
248*4882a593Smuzhiyun * To be able to use wildcard for domain transition, this function sets
249*4882a593Smuzhiyun * matching entry on success. Since the caller holds tomoyo_read_lock(),
250*4882a593Smuzhiyun * it is safe to set matching entry.
251*4882a593Smuzhiyun */
tomoyo_check_path_acl(struct tomoyo_request_info * r,const struct tomoyo_acl_info * ptr)252*4882a593Smuzhiyun static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
253*4882a593Smuzhiyun const struct tomoyo_acl_info *ptr)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
256*4882a593Smuzhiyun head);
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun if (acl->perm & (1 << r->param.path.operation)) {
259*4882a593Smuzhiyun r->param.path.matched_path =
260*4882a593Smuzhiyun tomoyo_compare_name_union(r->param.path.filename,
261*4882a593Smuzhiyun &acl->name);
262*4882a593Smuzhiyun return r->param.path.matched_path != NULL;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun return false;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /**
268*4882a593Smuzhiyun * tomoyo_check_path_number_acl - Check permission for path number operation.
269*4882a593Smuzhiyun *
270*4882a593Smuzhiyun * @r: Pointer to "struct tomoyo_request_info".
271*4882a593Smuzhiyun * @ptr: Pointer to "struct tomoyo_acl_info".
272*4882a593Smuzhiyun *
273*4882a593Smuzhiyun * Returns true if granted, false otherwise.
274*4882a593Smuzhiyun */
tomoyo_check_path_number_acl(struct tomoyo_request_info * r,const struct tomoyo_acl_info * ptr)275*4882a593Smuzhiyun static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
276*4882a593Smuzhiyun const struct tomoyo_acl_info *ptr)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun const struct tomoyo_path_number_acl *acl =
279*4882a593Smuzhiyun container_of(ptr, typeof(*acl), head);
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun return (acl->perm & (1 << r->param.path_number.operation)) &&
282*4882a593Smuzhiyun tomoyo_compare_number_union(r->param.path_number.number,
283*4882a593Smuzhiyun &acl->number) &&
284*4882a593Smuzhiyun tomoyo_compare_name_union(r->param.path_number.filename,
285*4882a593Smuzhiyun &acl->name);
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun /**
289*4882a593Smuzhiyun * tomoyo_check_path2_acl - Check permission for path path operation.
290*4882a593Smuzhiyun *
291*4882a593Smuzhiyun * @r: Pointer to "struct tomoyo_request_info".
292*4882a593Smuzhiyun * @ptr: Pointer to "struct tomoyo_acl_info".
293*4882a593Smuzhiyun *
294*4882a593Smuzhiyun * Returns true if granted, false otherwise.
295*4882a593Smuzhiyun */
tomoyo_check_path2_acl(struct tomoyo_request_info * r,const struct tomoyo_acl_info * ptr)296*4882a593Smuzhiyun static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
297*4882a593Smuzhiyun const struct tomoyo_acl_info *ptr)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun const struct tomoyo_path2_acl *acl =
300*4882a593Smuzhiyun container_of(ptr, typeof(*acl), head);
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun return (acl->perm & (1 << r->param.path2.operation)) &&
303*4882a593Smuzhiyun tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
304*4882a593Smuzhiyun && tomoyo_compare_name_union(r->param.path2.filename2,
305*4882a593Smuzhiyun &acl->name2);
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun /**
309*4882a593Smuzhiyun * tomoyo_check_mkdev_acl - Check permission for path number number number operation.
310*4882a593Smuzhiyun *
311*4882a593Smuzhiyun * @r: Pointer to "struct tomoyo_request_info".
312*4882a593Smuzhiyun * @ptr: Pointer to "struct tomoyo_acl_info".
313*4882a593Smuzhiyun *
314*4882a593Smuzhiyun * Returns true if granted, false otherwise.
315*4882a593Smuzhiyun */
tomoyo_check_mkdev_acl(struct tomoyo_request_info * r,const struct tomoyo_acl_info * ptr)316*4882a593Smuzhiyun static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
317*4882a593Smuzhiyun const struct tomoyo_acl_info *ptr)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun const struct tomoyo_mkdev_acl *acl =
320*4882a593Smuzhiyun container_of(ptr, typeof(*acl), head);
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun return (acl->perm & (1 << r->param.mkdev.operation)) &&
323*4882a593Smuzhiyun tomoyo_compare_number_union(r->param.mkdev.mode,
324*4882a593Smuzhiyun &acl->mode) &&
325*4882a593Smuzhiyun tomoyo_compare_number_union(r->param.mkdev.major,
326*4882a593Smuzhiyun &acl->major) &&
327*4882a593Smuzhiyun tomoyo_compare_number_union(r->param.mkdev.minor,
328*4882a593Smuzhiyun &acl->minor) &&
329*4882a593Smuzhiyun tomoyo_compare_name_union(r->param.mkdev.filename,
330*4882a593Smuzhiyun &acl->name);
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun /**
334*4882a593Smuzhiyun * tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry.
335*4882a593Smuzhiyun *
336*4882a593Smuzhiyun * @a: Pointer to "struct tomoyo_acl_info".
337*4882a593Smuzhiyun * @b: Pointer to "struct tomoyo_acl_info".
338*4882a593Smuzhiyun *
339*4882a593Smuzhiyun * Returns true if @a == @b except permission bits, false otherwise.
340*4882a593Smuzhiyun */
tomoyo_same_path_acl(const struct tomoyo_acl_info * a,const struct tomoyo_acl_info * b)341*4882a593Smuzhiyun static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
342*4882a593Smuzhiyun const struct tomoyo_acl_info *b)
343*4882a593Smuzhiyun {
344*4882a593Smuzhiyun const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
345*4882a593Smuzhiyun const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun return tomoyo_same_name_union(&p1->name, &p2->name);
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun /**
351*4882a593Smuzhiyun * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry.
352*4882a593Smuzhiyun *
353*4882a593Smuzhiyun * @a: Pointer to "struct tomoyo_acl_info".
354*4882a593Smuzhiyun * @b: Pointer to "struct tomoyo_acl_info".
355*4882a593Smuzhiyun * @is_delete: True for @a &= ~@b, false for @a |= @b.
356*4882a593Smuzhiyun *
357*4882a593Smuzhiyun * Returns true if @a is empty, false otherwise.
358*4882a593Smuzhiyun */
tomoyo_merge_path_acl(struct tomoyo_acl_info * a,struct tomoyo_acl_info * b,const bool is_delete)359*4882a593Smuzhiyun static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
360*4882a593Smuzhiyun struct tomoyo_acl_info *b,
361*4882a593Smuzhiyun const bool is_delete)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
364*4882a593Smuzhiyun ->perm;
365*4882a593Smuzhiyun u16 perm = READ_ONCE(*a_perm);
366*4882a593Smuzhiyun const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun if (is_delete)
369*4882a593Smuzhiyun perm &= ~b_perm;
370*4882a593Smuzhiyun else
371*4882a593Smuzhiyun perm |= b_perm;
372*4882a593Smuzhiyun WRITE_ONCE(*a_perm, perm);
373*4882a593Smuzhiyun return !perm;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun /**
377*4882a593Smuzhiyun * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
378*4882a593Smuzhiyun *
379*4882a593Smuzhiyun * @perm: Permission.
380*4882a593Smuzhiyun * @param: Pointer to "struct tomoyo_acl_param".
381*4882a593Smuzhiyun *
382*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
383*4882a593Smuzhiyun *
384*4882a593Smuzhiyun * Caller holds tomoyo_read_lock().
385*4882a593Smuzhiyun */
tomoyo_update_path_acl(const u16 perm,struct tomoyo_acl_param * param)386*4882a593Smuzhiyun static int tomoyo_update_path_acl(const u16 perm,
387*4882a593Smuzhiyun struct tomoyo_acl_param *param)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun struct tomoyo_path_acl e = {
390*4882a593Smuzhiyun .head.type = TOMOYO_TYPE_PATH_ACL,
391*4882a593Smuzhiyun .perm = perm
392*4882a593Smuzhiyun };
393*4882a593Smuzhiyun int error;
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun if (!tomoyo_parse_name_union(param, &e.name))
396*4882a593Smuzhiyun error = -EINVAL;
397*4882a593Smuzhiyun else
398*4882a593Smuzhiyun error = tomoyo_update_domain(&e.head, sizeof(e), param,
399*4882a593Smuzhiyun tomoyo_same_path_acl,
400*4882a593Smuzhiyun tomoyo_merge_path_acl);
401*4882a593Smuzhiyun tomoyo_put_name_union(&e.name);
402*4882a593Smuzhiyun return error;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun /**
406*4882a593Smuzhiyun * tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry.
407*4882a593Smuzhiyun *
408*4882a593Smuzhiyun * @a: Pointer to "struct tomoyo_acl_info".
409*4882a593Smuzhiyun * @b: Pointer to "struct tomoyo_acl_info".
410*4882a593Smuzhiyun *
411*4882a593Smuzhiyun * Returns true if @a == @b except permission bits, false otherwise.
412*4882a593Smuzhiyun */
tomoyo_same_mkdev_acl(const struct tomoyo_acl_info * a,const struct tomoyo_acl_info * b)413*4882a593Smuzhiyun static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
414*4882a593Smuzhiyun const struct tomoyo_acl_info *b)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head);
417*4882a593Smuzhiyun const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head);
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun return tomoyo_same_name_union(&p1->name, &p2->name) &&
420*4882a593Smuzhiyun tomoyo_same_number_union(&p1->mode, &p2->mode) &&
421*4882a593Smuzhiyun tomoyo_same_number_union(&p1->major, &p2->major) &&
422*4882a593Smuzhiyun tomoyo_same_number_union(&p1->minor, &p2->minor);
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun /**
426*4882a593Smuzhiyun * tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry.
427*4882a593Smuzhiyun *
428*4882a593Smuzhiyun * @a: Pointer to "struct tomoyo_acl_info".
429*4882a593Smuzhiyun * @b: Pointer to "struct tomoyo_acl_info".
430*4882a593Smuzhiyun * @is_delete: True for @a &= ~@b, false for @a |= @b.
431*4882a593Smuzhiyun *
432*4882a593Smuzhiyun * Returns true if @a is empty, false otherwise.
433*4882a593Smuzhiyun */
tomoyo_merge_mkdev_acl(struct tomoyo_acl_info * a,struct tomoyo_acl_info * b,const bool is_delete)434*4882a593Smuzhiyun static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
435*4882a593Smuzhiyun struct tomoyo_acl_info *b,
436*4882a593Smuzhiyun const bool is_delete)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
439*4882a593Smuzhiyun head)->perm;
440*4882a593Smuzhiyun u8 perm = READ_ONCE(*a_perm);
441*4882a593Smuzhiyun const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
442*4882a593Smuzhiyun ->perm;
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun if (is_delete)
445*4882a593Smuzhiyun perm &= ~b_perm;
446*4882a593Smuzhiyun else
447*4882a593Smuzhiyun perm |= b_perm;
448*4882a593Smuzhiyun WRITE_ONCE(*a_perm, perm);
449*4882a593Smuzhiyun return !perm;
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun /**
453*4882a593Smuzhiyun * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
454*4882a593Smuzhiyun *
455*4882a593Smuzhiyun * @perm: Permission.
456*4882a593Smuzhiyun * @param: Pointer to "struct tomoyo_acl_param".
457*4882a593Smuzhiyun *
458*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
459*4882a593Smuzhiyun *
460*4882a593Smuzhiyun * Caller holds tomoyo_read_lock().
461*4882a593Smuzhiyun */
tomoyo_update_mkdev_acl(const u8 perm,struct tomoyo_acl_param * param)462*4882a593Smuzhiyun static int tomoyo_update_mkdev_acl(const u8 perm,
463*4882a593Smuzhiyun struct tomoyo_acl_param *param)
464*4882a593Smuzhiyun {
465*4882a593Smuzhiyun struct tomoyo_mkdev_acl e = {
466*4882a593Smuzhiyun .head.type = TOMOYO_TYPE_MKDEV_ACL,
467*4882a593Smuzhiyun .perm = perm
468*4882a593Smuzhiyun };
469*4882a593Smuzhiyun int error;
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun if (!tomoyo_parse_name_union(param, &e.name) ||
472*4882a593Smuzhiyun !tomoyo_parse_number_union(param, &e.mode) ||
473*4882a593Smuzhiyun !tomoyo_parse_number_union(param, &e.major) ||
474*4882a593Smuzhiyun !tomoyo_parse_number_union(param, &e.minor))
475*4882a593Smuzhiyun error = -EINVAL;
476*4882a593Smuzhiyun else
477*4882a593Smuzhiyun error = tomoyo_update_domain(&e.head, sizeof(e), param,
478*4882a593Smuzhiyun tomoyo_same_mkdev_acl,
479*4882a593Smuzhiyun tomoyo_merge_mkdev_acl);
480*4882a593Smuzhiyun tomoyo_put_name_union(&e.name);
481*4882a593Smuzhiyun tomoyo_put_number_union(&e.mode);
482*4882a593Smuzhiyun tomoyo_put_number_union(&e.major);
483*4882a593Smuzhiyun tomoyo_put_number_union(&e.minor);
484*4882a593Smuzhiyun return error;
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun /**
488*4882a593Smuzhiyun * tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry.
489*4882a593Smuzhiyun *
490*4882a593Smuzhiyun * @a: Pointer to "struct tomoyo_acl_info".
491*4882a593Smuzhiyun * @b: Pointer to "struct tomoyo_acl_info".
492*4882a593Smuzhiyun *
493*4882a593Smuzhiyun * Returns true if @a == @b except permission bits, false otherwise.
494*4882a593Smuzhiyun */
tomoyo_same_path2_acl(const struct tomoyo_acl_info * a,const struct tomoyo_acl_info * b)495*4882a593Smuzhiyun static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
496*4882a593Smuzhiyun const struct tomoyo_acl_info *b)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
499*4882a593Smuzhiyun const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun return tomoyo_same_name_union(&p1->name1, &p2->name1) &&
502*4882a593Smuzhiyun tomoyo_same_name_union(&p1->name2, &p2->name2);
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun /**
506*4882a593Smuzhiyun * tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry.
507*4882a593Smuzhiyun *
508*4882a593Smuzhiyun * @a: Pointer to "struct tomoyo_acl_info".
509*4882a593Smuzhiyun * @b: Pointer to "struct tomoyo_acl_info".
510*4882a593Smuzhiyun * @is_delete: True for @a &= ~@b, false for @a |= @b.
511*4882a593Smuzhiyun *
512*4882a593Smuzhiyun * Returns true if @a is empty, false otherwise.
513*4882a593Smuzhiyun */
tomoyo_merge_path2_acl(struct tomoyo_acl_info * a,struct tomoyo_acl_info * b,const bool is_delete)514*4882a593Smuzhiyun static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
515*4882a593Smuzhiyun struct tomoyo_acl_info *b,
516*4882a593Smuzhiyun const bool is_delete)
517*4882a593Smuzhiyun {
518*4882a593Smuzhiyun u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
519*4882a593Smuzhiyun ->perm;
520*4882a593Smuzhiyun u8 perm = READ_ONCE(*a_perm);
521*4882a593Smuzhiyun const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun if (is_delete)
524*4882a593Smuzhiyun perm &= ~b_perm;
525*4882a593Smuzhiyun else
526*4882a593Smuzhiyun perm |= b_perm;
527*4882a593Smuzhiyun WRITE_ONCE(*a_perm, perm);
528*4882a593Smuzhiyun return !perm;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun /**
532*4882a593Smuzhiyun * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
533*4882a593Smuzhiyun *
534*4882a593Smuzhiyun * @perm: Permission.
535*4882a593Smuzhiyun * @param: Pointer to "struct tomoyo_acl_param".
536*4882a593Smuzhiyun *
537*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
538*4882a593Smuzhiyun *
539*4882a593Smuzhiyun * Caller holds tomoyo_read_lock().
540*4882a593Smuzhiyun */
tomoyo_update_path2_acl(const u8 perm,struct tomoyo_acl_param * param)541*4882a593Smuzhiyun static int tomoyo_update_path2_acl(const u8 perm,
542*4882a593Smuzhiyun struct tomoyo_acl_param *param)
543*4882a593Smuzhiyun {
544*4882a593Smuzhiyun struct tomoyo_path2_acl e = {
545*4882a593Smuzhiyun .head.type = TOMOYO_TYPE_PATH2_ACL,
546*4882a593Smuzhiyun .perm = perm
547*4882a593Smuzhiyun };
548*4882a593Smuzhiyun int error;
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun if (!tomoyo_parse_name_union(param, &e.name1) ||
551*4882a593Smuzhiyun !tomoyo_parse_name_union(param, &e.name2))
552*4882a593Smuzhiyun error = -EINVAL;
553*4882a593Smuzhiyun else
554*4882a593Smuzhiyun error = tomoyo_update_domain(&e.head, sizeof(e), param,
555*4882a593Smuzhiyun tomoyo_same_path2_acl,
556*4882a593Smuzhiyun tomoyo_merge_path2_acl);
557*4882a593Smuzhiyun tomoyo_put_name_union(&e.name1);
558*4882a593Smuzhiyun tomoyo_put_name_union(&e.name2);
559*4882a593Smuzhiyun return error;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun /**
563*4882a593Smuzhiyun * tomoyo_path_permission - Check permission for single path operation.
564*4882a593Smuzhiyun *
565*4882a593Smuzhiyun * @r: Pointer to "struct tomoyo_request_info".
566*4882a593Smuzhiyun * @operation: Type of operation.
567*4882a593Smuzhiyun * @filename: Filename to check.
568*4882a593Smuzhiyun *
569*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
570*4882a593Smuzhiyun *
571*4882a593Smuzhiyun * Caller holds tomoyo_read_lock().
572*4882a593Smuzhiyun */
tomoyo_path_permission(struct tomoyo_request_info * r,u8 operation,const struct tomoyo_path_info * filename)573*4882a593Smuzhiyun static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
574*4882a593Smuzhiyun const struct tomoyo_path_info *filename)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun int error;
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun r->type = tomoyo_p2mac[operation];
579*4882a593Smuzhiyun r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
580*4882a593Smuzhiyun if (r->mode == TOMOYO_CONFIG_DISABLED)
581*4882a593Smuzhiyun return 0;
582*4882a593Smuzhiyun r->param_type = TOMOYO_TYPE_PATH_ACL;
583*4882a593Smuzhiyun r->param.path.filename = filename;
584*4882a593Smuzhiyun r->param.path.operation = operation;
585*4882a593Smuzhiyun do {
586*4882a593Smuzhiyun tomoyo_check_acl(r, tomoyo_check_path_acl);
587*4882a593Smuzhiyun error = tomoyo_audit_path_log(r);
588*4882a593Smuzhiyun } while (error == TOMOYO_RETRY_REQUEST);
589*4882a593Smuzhiyun return error;
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun /**
593*4882a593Smuzhiyun * tomoyo_execute_permission - Check permission for execute operation.
594*4882a593Smuzhiyun *
595*4882a593Smuzhiyun * @r: Pointer to "struct tomoyo_request_info".
596*4882a593Smuzhiyun * @filename: Filename to check.
597*4882a593Smuzhiyun *
598*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
599*4882a593Smuzhiyun *
600*4882a593Smuzhiyun * Caller holds tomoyo_read_lock().
601*4882a593Smuzhiyun */
tomoyo_execute_permission(struct tomoyo_request_info * r,const struct tomoyo_path_info * filename)602*4882a593Smuzhiyun int tomoyo_execute_permission(struct tomoyo_request_info *r,
603*4882a593Smuzhiyun const struct tomoyo_path_info *filename)
604*4882a593Smuzhiyun {
605*4882a593Smuzhiyun /*
606*4882a593Smuzhiyun * Unlike other permission checks, this check is done regardless of
607*4882a593Smuzhiyun * profile mode settings in order to check for domain transition
608*4882a593Smuzhiyun * preference.
609*4882a593Smuzhiyun */
610*4882a593Smuzhiyun r->type = TOMOYO_MAC_FILE_EXECUTE;
611*4882a593Smuzhiyun r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
612*4882a593Smuzhiyun r->param_type = TOMOYO_TYPE_PATH_ACL;
613*4882a593Smuzhiyun r->param.path.filename = filename;
614*4882a593Smuzhiyun r->param.path.operation = TOMOYO_TYPE_EXECUTE;
615*4882a593Smuzhiyun tomoyo_check_acl(r, tomoyo_check_path_acl);
616*4882a593Smuzhiyun r->ee->transition = r->matched_acl && r->matched_acl->cond ?
617*4882a593Smuzhiyun r->matched_acl->cond->transit : NULL;
618*4882a593Smuzhiyun if (r->mode != TOMOYO_CONFIG_DISABLED)
619*4882a593Smuzhiyun return tomoyo_audit_path_log(r);
620*4882a593Smuzhiyun return 0;
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun /**
624*4882a593Smuzhiyun * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry.
625*4882a593Smuzhiyun *
626*4882a593Smuzhiyun * @a: Pointer to "struct tomoyo_acl_info".
627*4882a593Smuzhiyun * @b: Pointer to "struct tomoyo_acl_info".
628*4882a593Smuzhiyun *
629*4882a593Smuzhiyun * Returns true if @a == @b except permission bits, false otherwise.
630*4882a593Smuzhiyun */
tomoyo_same_path_number_acl(const struct tomoyo_acl_info * a,const struct tomoyo_acl_info * b)631*4882a593Smuzhiyun static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
632*4882a593Smuzhiyun const struct tomoyo_acl_info *b)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
635*4882a593Smuzhiyun head);
636*4882a593Smuzhiyun const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
637*4882a593Smuzhiyun head);
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun return tomoyo_same_name_union(&p1->name, &p2->name) &&
640*4882a593Smuzhiyun tomoyo_same_number_union(&p1->number, &p2->number);
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun /**
644*4882a593Smuzhiyun * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry.
645*4882a593Smuzhiyun *
646*4882a593Smuzhiyun * @a: Pointer to "struct tomoyo_acl_info".
647*4882a593Smuzhiyun * @b: Pointer to "struct tomoyo_acl_info".
648*4882a593Smuzhiyun * @is_delete: True for @a &= ~@b, false for @a |= @b.
649*4882a593Smuzhiyun *
650*4882a593Smuzhiyun * Returns true if @a is empty, false otherwise.
651*4882a593Smuzhiyun */
tomoyo_merge_path_number_acl(struct tomoyo_acl_info * a,struct tomoyo_acl_info * b,const bool is_delete)652*4882a593Smuzhiyun static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
653*4882a593Smuzhiyun struct tomoyo_acl_info *b,
654*4882a593Smuzhiyun const bool is_delete)
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
657*4882a593Smuzhiyun head)->perm;
658*4882a593Smuzhiyun u8 perm = READ_ONCE(*a_perm);
659*4882a593Smuzhiyun const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
660*4882a593Smuzhiyun ->perm;
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun if (is_delete)
663*4882a593Smuzhiyun perm &= ~b_perm;
664*4882a593Smuzhiyun else
665*4882a593Smuzhiyun perm |= b_perm;
666*4882a593Smuzhiyun WRITE_ONCE(*a_perm, perm);
667*4882a593Smuzhiyun return !perm;
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun /**
671*4882a593Smuzhiyun * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
672*4882a593Smuzhiyun *
673*4882a593Smuzhiyun * @perm: Permission.
674*4882a593Smuzhiyun * @param: Pointer to "struct tomoyo_acl_param".
675*4882a593Smuzhiyun *
676*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
677*4882a593Smuzhiyun */
tomoyo_update_path_number_acl(const u8 perm,struct tomoyo_acl_param * param)678*4882a593Smuzhiyun static int tomoyo_update_path_number_acl(const u8 perm,
679*4882a593Smuzhiyun struct tomoyo_acl_param *param)
680*4882a593Smuzhiyun {
681*4882a593Smuzhiyun struct tomoyo_path_number_acl e = {
682*4882a593Smuzhiyun .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
683*4882a593Smuzhiyun .perm = perm
684*4882a593Smuzhiyun };
685*4882a593Smuzhiyun int error;
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun if (!tomoyo_parse_name_union(param, &e.name) ||
688*4882a593Smuzhiyun !tomoyo_parse_number_union(param, &e.number))
689*4882a593Smuzhiyun error = -EINVAL;
690*4882a593Smuzhiyun else
691*4882a593Smuzhiyun error = tomoyo_update_domain(&e.head, sizeof(e), param,
692*4882a593Smuzhiyun tomoyo_same_path_number_acl,
693*4882a593Smuzhiyun tomoyo_merge_path_number_acl);
694*4882a593Smuzhiyun tomoyo_put_name_union(&e.name);
695*4882a593Smuzhiyun tomoyo_put_number_union(&e.number);
696*4882a593Smuzhiyun return error;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun /**
700*4882a593Smuzhiyun * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
701*4882a593Smuzhiyun *
702*4882a593Smuzhiyun * @type: Type of operation.
703*4882a593Smuzhiyun * @path: Pointer to "struct path".
704*4882a593Smuzhiyun * @number: Number.
705*4882a593Smuzhiyun *
706*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
707*4882a593Smuzhiyun */
tomoyo_path_number_perm(const u8 type,const struct path * path,unsigned long number)708*4882a593Smuzhiyun int tomoyo_path_number_perm(const u8 type, const struct path *path,
709*4882a593Smuzhiyun unsigned long number)
710*4882a593Smuzhiyun {
711*4882a593Smuzhiyun struct tomoyo_request_info r;
712*4882a593Smuzhiyun struct tomoyo_obj_info obj = {
713*4882a593Smuzhiyun .path1 = { .mnt = path->mnt, .dentry = path->dentry },
714*4882a593Smuzhiyun };
715*4882a593Smuzhiyun int error = -ENOMEM;
716*4882a593Smuzhiyun struct tomoyo_path_info buf;
717*4882a593Smuzhiyun int idx;
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
720*4882a593Smuzhiyun == TOMOYO_CONFIG_DISABLED || !path->dentry)
721*4882a593Smuzhiyun return 0;
722*4882a593Smuzhiyun idx = tomoyo_read_lock();
723*4882a593Smuzhiyun if (!tomoyo_get_realpath(&buf, path))
724*4882a593Smuzhiyun goto out;
725*4882a593Smuzhiyun r.obj = &obj;
726*4882a593Smuzhiyun if (type == TOMOYO_TYPE_MKDIR)
727*4882a593Smuzhiyun tomoyo_add_slash(&buf);
728*4882a593Smuzhiyun r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
729*4882a593Smuzhiyun r.param.path_number.operation = type;
730*4882a593Smuzhiyun r.param.path_number.filename = &buf;
731*4882a593Smuzhiyun r.param.path_number.number = number;
732*4882a593Smuzhiyun do {
733*4882a593Smuzhiyun tomoyo_check_acl(&r, tomoyo_check_path_number_acl);
734*4882a593Smuzhiyun error = tomoyo_audit_path_number_log(&r);
735*4882a593Smuzhiyun } while (error == TOMOYO_RETRY_REQUEST);
736*4882a593Smuzhiyun kfree(buf.name);
737*4882a593Smuzhiyun out:
738*4882a593Smuzhiyun tomoyo_read_unlock(idx);
739*4882a593Smuzhiyun if (r.mode != TOMOYO_CONFIG_ENFORCING)
740*4882a593Smuzhiyun error = 0;
741*4882a593Smuzhiyun return error;
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun /**
745*4882a593Smuzhiyun * tomoyo_check_open_permission - Check permission for "read" and "write".
746*4882a593Smuzhiyun *
747*4882a593Smuzhiyun * @domain: Pointer to "struct tomoyo_domain_info".
748*4882a593Smuzhiyun * @path: Pointer to "struct path".
749*4882a593Smuzhiyun * @flag: Flags for open().
750*4882a593Smuzhiyun *
751*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
752*4882a593Smuzhiyun */
tomoyo_check_open_permission(struct tomoyo_domain_info * domain,const struct path * path,const int flag)753*4882a593Smuzhiyun int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
754*4882a593Smuzhiyun const struct path *path, const int flag)
755*4882a593Smuzhiyun {
756*4882a593Smuzhiyun const u8 acc_mode = ACC_MODE(flag);
757*4882a593Smuzhiyun int error = 0;
758*4882a593Smuzhiyun struct tomoyo_path_info buf;
759*4882a593Smuzhiyun struct tomoyo_request_info r;
760*4882a593Smuzhiyun struct tomoyo_obj_info obj = {
761*4882a593Smuzhiyun .path1 = { .mnt = path->mnt, .dentry = path->dentry },
762*4882a593Smuzhiyun };
763*4882a593Smuzhiyun int idx;
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun buf.name = NULL;
766*4882a593Smuzhiyun r.mode = TOMOYO_CONFIG_DISABLED;
767*4882a593Smuzhiyun idx = tomoyo_read_lock();
768*4882a593Smuzhiyun if (acc_mode &&
769*4882a593Smuzhiyun tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
770*4882a593Smuzhiyun != TOMOYO_CONFIG_DISABLED) {
771*4882a593Smuzhiyun if (!tomoyo_get_realpath(&buf, path)) {
772*4882a593Smuzhiyun error = -ENOMEM;
773*4882a593Smuzhiyun goto out;
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun r.obj = &obj;
776*4882a593Smuzhiyun if (acc_mode & MAY_READ)
777*4882a593Smuzhiyun error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ,
778*4882a593Smuzhiyun &buf);
779*4882a593Smuzhiyun if (!error && (acc_mode & MAY_WRITE))
780*4882a593Smuzhiyun error = tomoyo_path_permission(&r, (flag & O_APPEND) ?
781*4882a593Smuzhiyun TOMOYO_TYPE_APPEND :
782*4882a593Smuzhiyun TOMOYO_TYPE_WRITE,
783*4882a593Smuzhiyun &buf);
784*4882a593Smuzhiyun }
785*4882a593Smuzhiyun out:
786*4882a593Smuzhiyun kfree(buf.name);
787*4882a593Smuzhiyun tomoyo_read_unlock(idx);
788*4882a593Smuzhiyun if (r.mode != TOMOYO_CONFIG_ENFORCING)
789*4882a593Smuzhiyun error = 0;
790*4882a593Smuzhiyun return error;
791*4882a593Smuzhiyun }
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun /**
794*4882a593Smuzhiyun * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount".
795*4882a593Smuzhiyun *
796*4882a593Smuzhiyun * @operation: Type of operation.
797*4882a593Smuzhiyun * @path: Pointer to "struct path".
798*4882a593Smuzhiyun * @target: Symlink's target if @operation is TOMOYO_TYPE_SYMLINK,
799*4882a593Smuzhiyun * NULL otherwise.
800*4882a593Smuzhiyun *
801*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
802*4882a593Smuzhiyun */
tomoyo_path_perm(const u8 operation,const struct path * path,const char * target)803*4882a593Smuzhiyun int tomoyo_path_perm(const u8 operation, const struct path *path, const char *target)
804*4882a593Smuzhiyun {
805*4882a593Smuzhiyun struct tomoyo_request_info r;
806*4882a593Smuzhiyun struct tomoyo_obj_info obj = {
807*4882a593Smuzhiyun .path1 = { .mnt = path->mnt, .dentry = path->dentry },
808*4882a593Smuzhiyun };
809*4882a593Smuzhiyun int error;
810*4882a593Smuzhiyun struct tomoyo_path_info buf;
811*4882a593Smuzhiyun bool is_enforce;
812*4882a593Smuzhiyun struct tomoyo_path_info symlink_target;
813*4882a593Smuzhiyun int idx;
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
816*4882a593Smuzhiyun == TOMOYO_CONFIG_DISABLED)
817*4882a593Smuzhiyun return 0;
818*4882a593Smuzhiyun is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING);
819*4882a593Smuzhiyun error = -ENOMEM;
820*4882a593Smuzhiyun buf.name = NULL;
821*4882a593Smuzhiyun idx = tomoyo_read_lock();
822*4882a593Smuzhiyun if (!tomoyo_get_realpath(&buf, path))
823*4882a593Smuzhiyun goto out;
824*4882a593Smuzhiyun r.obj = &obj;
825*4882a593Smuzhiyun switch (operation) {
826*4882a593Smuzhiyun case TOMOYO_TYPE_RMDIR:
827*4882a593Smuzhiyun case TOMOYO_TYPE_CHROOT:
828*4882a593Smuzhiyun tomoyo_add_slash(&buf);
829*4882a593Smuzhiyun break;
830*4882a593Smuzhiyun case TOMOYO_TYPE_SYMLINK:
831*4882a593Smuzhiyun symlink_target.name = tomoyo_encode(target);
832*4882a593Smuzhiyun if (!symlink_target.name)
833*4882a593Smuzhiyun goto out;
834*4882a593Smuzhiyun tomoyo_fill_path_info(&symlink_target);
835*4882a593Smuzhiyun obj.symlink_target = &symlink_target;
836*4882a593Smuzhiyun break;
837*4882a593Smuzhiyun }
838*4882a593Smuzhiyun error = tomoyo_path_permission(&r, operation, &buf);
839*4882a593Smuzhiyun if (operation == TOMOYO_TYPE_SYMLINK)
840*4882a593Smuzhiyun kfree(symlink_target.name);
841*4882a593Smuzhiyun out:
842*4882a593Smuzhiyun kfree(buf.name);
843*4882a593Smuzhiyun tomoyo_read_unlock(idx);
844*4882a593Smuzhiyun if (!is_enforce)
845*4882a593Smuzhiyun error = 0;
846*4882a593Smuzhiyun return error;
847*4882a593Smuzhiyun }
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun /**
850*4882a593Smuzhiyun * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar".
851*4882a593Smuzhiyun *
852*4882a593Smuzhiyun * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK)
853*4882a593Smuzhiyun * @path: Pointer to "struct path".
854*4882a593Smuzhiyun * @mode: Create mode.
855*4882a593Smuzhiyun * @dev: Device number.
856*4882a593Smuzhiyun *
857*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
858*4882a593Smuzhiyun */
tomoyo_mkdev_perm(const u8 operation,const struct path * path,const unsigned int mode,unsigned int dev)859*4882a593Smuzhiyun int tomoyo_mkdev_perm(const u8 operation, const struct path *path,
860*4882a593Smuzhiyun const unsigned int mode, unsigned int dev)
861*4882a593Smuzhiyun {
862*4882a593Smuzhiyun struct tomoyo_request_info r;
863*4882a593Smuzhiyun struct tomoyo_obj_info obj = {
864*4882a593Smuzhiyun .path1 = { .mnt = path->mnt, .dentry = path->dentry },
865*4882a593Smuzhiyun };
866*4882a593Smuzhiyun int error = -ENOMEM;
867*4882a593Smuzhiyun struct tomoyo_path_info buf;
868*4882a593Smuzhiyun int idx;
869*4882a593Smuzhiyun
870*4882a593Smuzhiyun if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
871*4882a593Smuzhiyun == TOMOYO_CONFIG_DISABLED)
872*4882a593Smuzhiyun return 0;
873*4882a593Smuzhiyun idx = tomoyo_read_lock();
874*4882a593Smuzhiyun error = -ENOMEM;
875*4882a593Smuzhiyun if (tomoyo_get_realpath(&buf, path)) {
876*4882a593Smuzhiyun r.obj = &obj;
877*4882a593Smuzhiyun dev = new_decode_dev(dev);
878*4882a593Smuzhiyun r.param_type = TOMOYO_TYPE_MKDEV_ACL;
879*4882a593Smuzhiyun r.param.mkdev.filename = &buf;
880*4882a593Smuzhiyun r.param.mkdev.operation = operation;
881*4882a593Smuzhiyun r.param.mkdev.mode = mode;
882*4882a593Smuzhiyun r.param.mkdev.major = MAJOR(dev);
883*4882a593Smuzhiyun r.param.mkdev.minor = MINOR(dev);
884*4882a593Smuzhiyun tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
885*4882a593Smuzhiyun error = tomoyo_audit_mkdev_log(&r);
886*4882a593Smuzhiyun kfree(buf.name);
887*4882a593Smuzhiyun }
888*4882a593Smuzhiyun tomoyo_read_unlock(idx);
889*4882a593Smuzhiyun if (r.mode != TOMOYO_CONFIG_ENFORCING)
890*4882a593Smuzhiyun error = 0;
891*4882a593Smuzhiyun return error;
892*4882a593Smuzhiyun }
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun /**
895*4882a593Smuzhiyun * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root".
896*4882a593Smuzhiyun *
897*4882a593Smuzhiyun * @operation: Type of operation.
898*4882a593Smuzhiyun * @path1: Pointer to "struct path".
899*4882a593Smuzhiyun * @path2: Pointer to "struct path".
900*4882a593Smuzhiyun *
901*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
902*4882a593Smuzhiyun */
tomoyo_path2_perm(const u8 operation,const struct path * path1,const struct path * path2)903*4882a593Smuzhiyun int tomoyo_path2_perm(const u8 operation, const struct path *path1,
904*4882a593Smuzhiyun const struct path *path2)
905*4882a593Smuzhiyun {
906*4882a593Smuzhiyun int error = -ENOMEM;
907*4882a593Smuzhiyun struct tomoyo_path_info buf1;
908*4882a593Smuzhiyun struct tomoyo_path_info buf2;
909*4882a593Smuzhiyun struct tomoyo_request_info r;
910*4882a593Smuzhiyun struct tomoyo_obj_info obj = {
911*4882a593Smuzhiyun .path1 = { .mnt = path1->mnt, .dentry = path1->dentry },
912*4882a593Smuzhiyun .path2 = { .mnt = path2->mnt, .dentry = path2->dentry }
913*4882a593Smuzhiyun };
914*4882a593Smuzhiyun int idx;
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
917*4882a593Smuzhiyun == TOMOYO_CONFIG_DISABLED)
918*4882a593Smuzhiyun return 0;
919*4882a593Smuzhiyun buf1.name = NULL;
920*4882a593Smuzhiyun buf2.name = NULL;
921*4882a593Smuzhiyun idx = tomoyo_read_lock();
922*4882a593Smuzhiyun if (!tomoyo_get_realpath(&buf1, path1) ||
923*4882a593Smuzhiyun !tomoyo_get_realpath(&buf2, path2))
924*4882a593Smuzhiyun goto out;
925*4882a593Smuzhiyun switch (operation) {
926*4882a593Smuzhiyun case TOMOYO_TYPE_RENAME:
927*4882a593Smuzhiyun case TOMOYO_TYPE_LINK:
928*4882a593Smuzhiyun if (!d_is_dir(path1->dentry))
929*4882a593Smuzhiyun break;
930*4882a593Smuzhiyun fallthrough;
931*4882a593Smuzhiyun case TOMOYO_TYPE_PIVOT_ROOT:
932*4882a593Smuzhiyun tomoyo_add_slash(&buf1);
933*4882a593Smuzhiyun tomoyo_add_slash(&buf2);
934*4882a593Smuzhiyun break;
935*4882a593Smuzhiyun }
936*4882a593Smuzhiyun r.obj = &obj;
937*4882a593Smuzhiyun r.param_type = TOMOYO_TYPE_PATH2_ACL;
938*4882a593Smuzhiyun r.param.path2.operation = operation;
939*4882a593Smuzhiyun r.param.path2.filename1 = &buf1;
940*4882a593Smuzhiyun r.param.path2.filename2 = &buf2;
941*4882a593Smuzhiyun do {
942*4882a593Smuzhiyun tomoyo_check_acl(&r, tomoyo_check_path2_acl);
943*4882a593Smuzhiyun error = tomoyo_audit_path2_log(&r);
944*4882a593Smuzhiyun } while (error == TOMOYO_RETRY_REQUEST);
945*4882a593Smuzhiyun out:
946*4882a593Smuzhiyun kfree(buf1.name);
947*4882a593Smuzhiyun kfree(buf2.name);
948*4882a593Smuzhiyun tomoyo_read_unlock(idx);
949*4882a593Smuzhiyun if (r.mode != TOMOYO_CONFIG_ENFORCING)
950*4882a593Smuzhiyun error = 0;
951*4882a593Smuzhiyun return error;
952*4882a593Smuzhiyun }
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun /**
955*4882a593Smuzhiyun * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry.
956*4882a593Smuzhiyun *
957*4882a593Smuzhiyun * @a: Pointer to "struct tomoyo_acl_info".
958*4882a593Smuzhiyun * @b: Pointer to "struct tomoyo_acl_info".
959*4882a593Smuzhiyun *
960*4882a593Smuzhiyun * Returns true if @a == @b, false otherwise.
961*4882a593Smuzhiyun */
tomoyo_same_mount_acl(const struct tomoyo_acl_info * a,const struct tomoyo_acl_info * b)962*4882a593Smuzhiyun static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
963*4882a593Smuzhiyun const struct tomoyo_acl_info *b)
964*4882a593Smuzhiyun {
965*4882a593Smuzhiyun const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
966*4882a593Smuzhiyun const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
969*4882a593Smuzhiyun tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
970*4882a593Smuzhiyun tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
971*4882a593Smuzhiyun tomoyo_same_number_union(&p1->flags, &p2->flags);
972*4882a593Smuzhiyun }
973*4882a593Smuzhiyun
974*4882a593Smuzhiyun /**
975*4882a593Smuzhiyun * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list.
976*4882a593Smuzhiyun *
977*4882a593Smuzhiyun * @param: Pointer to "struct tomoyo_acl_param".
978*4882a593Smuzhiyun *
979*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
980*4882a593Smuzhiyun *
981*4882a593Smuzhiyun * Caller holds tomoyo_read_lock().
982*4882a593Smuzhiyun */
tomoyo_update_mount_acl(struct tomoyo_acl_param * param)983*4882a593Smuzhiyun static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param)
984*4882a593Smuzhiyun {
985*4882a593Smuzhiyun struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
986*4882a593Smuzhiyun int error;
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun if (!tomoyo_parse_name_union(param, &e.dev_name) ||
989*4882a593Smuzhiyun !tomoyo_parse_name_union(param, &e.dir_name) ||
990*4882a593Smuzhiyun !tomoyo_parse_name_union(param, &e.fs_type) ||
991*4882a593Smuzhiyun !tomoyo_parse_number_union(param, &e.flags))
992*4882a593Smuzhiyun error = -EINVAL;
993*4882a593Smuzhiyun else
994*4882a593Smuzhiyun error = tomoyo_update_domain(&e.head, sizeof(e), param,
995*4882a593Smuzhiyun tomoyo_same_mount_acl, NULL);
996*4882a593Smuzhiyun tomoyo_put_name_union(&e.dev_name);
997*4882a593Smuzhiyun tomoyo_put_name_union(&e.dir_name);
998*4882a593Smuzhiyun tomoyo_put_name_union(&e.fs_type);
999*4882a593Smuzhiyun tomoyo_put_number_union(&e.flags);
1000*4882a593Smuzhiyun return error;
1001*4882a593Smuzhiyun }
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun /**
1004*4882a593Smuzhiyun * tomoyo_write_file - Update file related list.
1005*4882a593Smuzhiyun *
1006*4882a593Smuzhiyun * @param: Pointer to "struct tomoyo_acl_param".
1007*4882a593Smuzhiyun *
1008*4882a593Smuzhiyun * Returns 0 on success, negative value otherwise.
1009*4882a593Smuzhiyun *
1010*4882a593Smuzhiyun * Caller holds tomoyo_read_lock().
1011*4882a593Smuzhiyun */
tomoyo_write_file(struct tomoyo_acl_param * param)1012*4882a593Smuzhiyun int tomoyo_write_file(struct tomoyo_acl_param *param)
1013*4882a593Smuzhiyun {
1014*4882a593Smuzhiyun u16 perm = 0;
1015*4882a593Smuzhiyun u8 type;
1016*4882a593Smuzhiyun const char *operation = tomoyo_read_token(param);
1017*4882a593Smuzhiyun
1018*4882a593Smuzhiyun for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++)
1019*4882a593Smuzhiyun if (tomoyo_permstr(operation, tomoyo_path_keyword[type]))
1020*4882a593Smuzhiyun perm |= 1 << type;
1021*4882a593Smuzhiyun if (perm)
1022*4882a593Smuzhiyun return tomoyo_update_path_acl(perm, param);
1023*4882a593Smuzhiyun for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++)
1024*4882a593Smuzhiyun if (tomoyo_permstr(operation,
1025*4882a593Smuzhiyun tomoyo_mac_keywords[tomoyo_pp2mac[type]]))
1026*4882a593Smuzhiyun perm |= 1 << type;
1027*4882a593Smuzhiyun if (perm)
1028*4882a593Smuzhiyun return tomoyo_update_path2_acl(perm, param);
1029*4882a593Smuzhiyun for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++)
1030*4882a593Smuzhiyun if (tomoyo_permstr(operation,
1031*4882a593Smuzhiyun tomoyo_mac_keywords[tomoyo_pn2mac[type]]))
1032*4882a593Smuzhiyun perm |= 1 << type;
1033*4882a593Smuzhiyun if (perm)
1034*4882a593Smuzhiyun return tomoyo_update_path_number_acl(perm, param);
1035*4882a593Smuzhiyun for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++)
1036*4882a593Smuzhiyun if (tomoyo_permstr(operation,
1037*4882a593Smuzhiyun tomoyo_mac_keywords[tomoyo_pnnn2mac[type]]))
1038*4882a593Smuzhiyun perm |= 1 << type;
1039*4882a593Smuzhiyun if (perm)
1040*4882a593Smuzhiyun return tomoyo_update_mkdev_acl(perm, param);
1041*4882a593Smuzhiyun if (tomoyo_permstr(operation,
1042*4882a593Smuzhiyun tomoyo_mac_keywords[TOMOYO_MAC_FILE_MOUNT]))
1043*4882a593Smuzhiyun return tomoyo_update_mount_acl(param);
1044*4882a593Smuzhiyun return -EINVAL;
1045*4882a593Smuzhiyun }
1046