(empty log message)
@@ -1450,7 +1450,7 @@ | ||
1450 | 1450 | static int cs_old_open_permission(struct dentry *dentry, struct vfsmount *mnt, |
1451 | 1451 | const int flag) |
1452 | 1452 | { |
1453 | - struct path path = { mnt, dentry }; | |
1453 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
1454 | 1454 | return cs_open_permission(&path, flag); |
1455 | 1455 | } |
1456 | 1456 |
@@ -1590,7 +1590,7 @@ | ||
1590 | 1590 | static int cs_chmod_permission(struct dentry *dentry, struct vfsmount *vfsmnt, |
1591 | 1591 | mode_t mode) |
1592 | 1592 | { |
1593 | - struct path path = { vfsmnt, dentry }; | |
1593 | + struct path path = { .mnt = vfsmnt, .dentry = dentry }; | |
1594 | 1594 | return cs_path_number_perm(CS_MAC_CHMOD, &path, mode & S_IALLUGO); |
1595 | 1595 | } |
1596 | 1596 |
@@ -1610,7 +1610,7 @@ | ||
1610 | 1610 | kuid_t user, kgid_t group) |
1611 | 1611 | { |
1612 | 1612 | int error = 0; |
1613 | - struct path path = { vfsmnt, dentry }; | |
1613 | + struct path path = { .mnt = vfsmnt, .dentry = dentry }; | |
1614 | 1614 | if (uid_valid(user)) |
1615 | 1615 | error = cs_path_number_perm(CS_MAC_CHOWN, &path, |
1616 | 1616 | from_kuid(&init_user_ns, user)); |
@@ -1636,7 +1636,7 @@ | ||
1636 | 1636 | uid_t user, gid_t group) |
1637 | 1637 | { |
1638 | 1638 | int error = 0; |
1639 | - struct path path = { vfsmnt, dentry }; | |
1639 | + struct path path = { .mnt = vfsmnt, .dentry = dentry }; | |
1640 | 1640 | if (user == (uid_t) -1 && group == (gid_t) -1) |
1641 | 1641 | return 0; |
1642 | 1642 | if (user != (uid_t) -1) |
@@ -1708,7 +1708,7 @@ | ||
1708 | 1708 | */ |
1709 | 1709 | static int cs_umount_permission(struct vfsmount *mnt, int flags) |
1710 | 1710 | { |
1711 | - struct path path = { mnt, mnt->mnt_root }; | |
1711 | + struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; | |
1712 | 1712 | return cs_path_number_perm(CS_MAC_UMOUNT, &path, flags); |
1713 | 1713 | } |
1714 | 1714 |
@@ -1727,7 +1727,7 @@ | ||
1727 | 1727 | { |
1728 | 1728 | int error = 0; |
1729 | 1729 | const unsigned int perm = mode & S_IALLUGO; |
1730 | - struct path path = { mnt, dentry }; | |
1730 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
1731 | 1731 | switch (mode & S_IFMT) { |
1732 | 1732 | case S_IFCHR: |
1733 | 1733 | error = cs_mkdev_perm(CS_MAC_MKCHAR, &path, perm, dev); |
@@ -1761,7 +1761,7 @@ | ||
1761 | 1761 | static int cs_mkdir_permission(struct dentry *dentry, struct vfsmount *mnt, |
1762 | 1762 | unsigned int mode) |
1763 | 1763 | { |
1764 | - struct path path = { mnt, dentry }; | |
1764 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
1765 | 1765 | return cs_path_number_perm(CS_MAC_MKDIR, &path, mode); |
1766 | 1766 | } |
1767 | 1767 |
@@ -1775,7 +1775,7 @@ | ||
1775 | 1775 | */ |
1776 | 1776 | static int cs_rmdir_permission(struct dentry *dentry, struct vfsmount *mnt) |
1777 | 1777 | { |
1778 | - struct path path = { mnt, dentry }; | |
1778 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
1779 | 1779 | return cs_path_perm(CS_MAC_RMDIR, &path); |
1780 | 1780 | } |
1781 | 1781 |
@@ -1789,7 +1789,7 @@ | ||
1789 | 1789 | */ |
1790 | 1790 | static int cs_unlink_permission(struct dentry *dentry, struct vfsmount *mnt) |
1791 | 1791 | { |
1792 | - struct path path = { mnt, dentry }; | |
1792 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
1793 | 1793 | return cs_path_perm(CS_MAC_UNLINK, &path); |
1794 | 1794 | } |
1795 | 1795 |
@@ -1805,7 +1805,7 @@ | ||
1805 | 1805 | */ |
1806 | 1806 | static int cs_getattr_permission(struct vfsmount *mnt, struct dentry *dentry) |
1807 | 1807 | { |
1808 | - struct path path = { mnt, dentry }; | |
1808 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
1809 | 1809 | return cs_path_perm(CS_MAC_GETATTR, &path); |
1810 | 1810 | } |
1811 | 1811 |
@@ -1821,7 +1821,7 @@ | ||
1821 | 1821 | */ |
1822 | 1822 | static int cs_truncate_permission(struct dentry *dentry, struct vfsmount *mnt) |
1823 | 1823 | { |
1824 | - struct path path = { mnt, dentry }; | |
1824 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
1825 | 1825 | return cs_path_perm(CS_MAC_TRUNCATE, &path); |
1826 | 1826 | } |
1827 | 1827 |
@@ -1838,8 +1838,8 @@ | ||
1838 | 1838 | struct dentry *new_dentry, |
1839 | 1839 | struct vfsmount *mnt) |
1840 | 1840 | { |
1841 | - struct path old = { mnt, old_dentry }; | |
1842 | - struct path new = { mnt, new_dentry }; | |
1841 | + struct path old = { .mnt = mnt, .dentry = old_dentry }; | |
1842 | + struct path new = { .mnt = mnt, .dentry = new_dentry }; | |
1843 | 1843 | return cs_path2_perm(CS_MAC_RENAME, &old, &new); |
1844 | 1844 | } |
1845 | 1845 |
@@ -1855,8 +1855,8 @@ | ||
1855 | 1855 | static int cs_link_permission(struct dentry *old_dentry, |
1856 | 1856 | struct dentry *new_dentry, struct vfsmount *mnt) |
1857 | 1857 | { |
1858 | - struct path old = { mnt, old_dentry }; | |
1859 | - struct path new = { mnt, new_dentry }; | |
1858 | + struct path old = { .mnt = mnt, .dentry = old_dentry }; | |
1859 | + struct path new = { .mnt = mnt, .dentry = new_dentry }; | |
1860 | 1860 | return cs_path2_perm(CS_MAC_LINK, &old, &new); |
1861 | 1861 | } |
1862 | 1862 |
@@ -1872,7 +1872,7 @@ | ||
1872 | 1872 | */ |
1873 | 1873 | static int cs_open_exec_permission(struct dentry *dentry, struct vfsmount *mnt) |
1874 | 1874 | { |
1875 | - struct path path = { mnt, dentry }; | |
1875 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
1876 | 1876 | return (cs_current_flags() & CS_TASK_IS_IN_EXECVE) ? |
1877 | 1877 | cs_open_permission(&path, O_RDONLY + 1) : 0; |
1878 | 1878 | } |
@@ -1887,7 +1887,7 @@ | ||
1887 | 1887 | */ |
1888 | 1888 | static int cs_uselib_permission(struct dentry *dentry, struct vfsmount *mnt) |
1889 | 1889 | { |
1890 | - struct path path = { mnt, dentry }; | |
1890 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
1891 | 1891 | return cs_open_permission(&path, O_RDONLY + 1); |
1892 | 1892 | } |
1893 | 1893 |
@@ -1,1508 +0,0 @@ | ||
1 | -/* | |
2 | - * mclsm.c | |
3 | - * | |
4 | - * Copyright (C) 2010-2013 Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | |
5 | - * | |
6 | - * Version: 0.1.15 2015/08/06 | |
7 | - */ | |
8 | - | |
9 | -#include "caitsith.h" | |
10 | -#include "probe.h" | |
11 | - | |
12 | -/* Prototype definition. */ | |
13 | -static void cs_task_security_gc(void); | |
14 | -static int cs_copy_cred_security(const struct cred *new, | |
15 | - const struct cred *old, gfp_t gfp); | |
16 | -static struct cs_security *cs_find_cred_security(const struct cred *cred); | |
17 | -static DEFINE_SPINLOCK(cs_task_security_list_lock); | |
18 | -static atomic_t cs_in_execve_tasks = ATOMIC_INIT(0); | |
19 | -/* | |
20 | - * List of "struct cs_security" for "struct pid". | |
21 | - * | |
22 | - * All instances on this list is guaranteed that "struct cs_security"->pid != | |
23 | - * NULL. Also, instances on this list that are in execve() are guaranteed that | |
24 | - * "struct cs_security"->cred remembers "struct linux_binprm"->cred with a | |
25 | - * refcount on "struct linux_binprm"->cred. | |
26 | - */ | |
27 | -struct list_head cs_task_security_list[CS_MAX_TASK_SECURITY_HASH]; | |
28 | -/* | |
29 | - * List of "struct cs_security" for "struct cred". | |
30 | - * | |
31 | - * Since the number of "struct cred" is nearly equals to the number of | |
32 | - * "struct pid", we allocate hash tables like cs_task_security_list. | |
33 | - * | |
34 | - * All instances on this list are guaranteed that "struct cs_security"->pid == | |
35 | - * NULL and "struct cs_security"->cred != NULL. | |
36 | - */ | |
37 | -static struct list_head cs_cred_security_list[CS_MAX_TASK_SECURITY_HASH]; | |
38 | - | |
39 | -/* Dummy security context for avoiding NULL pointer dereference. */ | |
40 | -static struct cs_security cs_oom_security = { | |
41 | - .cs_domain_info = &cs_kernel_domain | |
42 | -}; | |
43 | - | |
44 | -/* Dummy security context for avoiding NULL pointer dereference. */ | |
45 | -static struct cs_security cs_default_security = { | |
46 | - .cs_domain_info = &cs_kernel_domain | |
47 | -}; | |
48 | - | |
49 | -/* For exporting variables and functions. */ | |
50 | -struct caitsith_exports caitsith_exports; | |
51 | - | |
52 | -/* Original hooks. */ | |
53 | -static union security_list_options original_cred_prepare; | |
54 | -static union security_list_options original_cred_free; | |
55 | -static union security_list_options original_cred_alloc_blank; | |
56 | - | |
57 | -#if !defined(CONFIG_CAITSITH_DEBUG) | |
58 | -#define cs_debug_trace(pos) do { } while (0) | |
59 | -#else | |
60 | -#define cs_debug_trace(pos) \ | |
61 | - do { \ | |
62 | - static bool done; \ | |
63 | - if (!done) { \ | |
64 | - printk(KERN_INFO \ | |
65 | - "CAITSITH: Debug trace: " pos " of 4\n"); \ | |
66 | - done = true; \ | |
67 | - } \ | |
68 | - } while (0) | |
69 | -#endif | |
70 | - | |
71 | -/** | |
72 | - * cs_clear_execve - Release memory used by do_execve(). | |
73 | - * | |
74 | - * @ret: 0 if do_execve() succeeded, negative value otherwise. | |
75 | - * @security: Pointer to "struct cs_security". | |
76 | - * | |
77 | - * Returns nothing. | |
78 | - */ | |
79 | -static void cs_clear_execve(int ret, struct cs_security *security) | |
80 | -{ | |
81 | - struct cs_request_info *r; | |
82 | - if (security == &cs_default_security || security == &cs_oom_security) | |
83 | - return; | |
84 | - r = security->r; | |
85 | - security->r = NULL; | |
86 | - if (!r) | |
87 | - return; | |
88 | - atomic_dec(&cs_in_execve_tasks); | |
89 | - cs_finish_execve(ret, r); | |
90 | -} | |
91 | - | |
92 | -/** | |
93 | - * cs_rcu_free - RCU callback for releasing "struct cs_security". | |
94 | - * | |
95 | - * @rcu: Pointer to "struct rcu_head". | |
96 | - * | |
97 | - * Returns nothing. | |
98 | - */ | |
99 | -static void cs_rcu_free(struct rcu_head *rcu) | |
100 | -{ | |
101 | - struct cs_security *ptr = container_of(rcu, typeof(*ptr), rcu); | |
102 | - struct cs_request_info *r = ptr->r; | |
103 | - /* | |
104 | - * If this security context was associated with "struct pid" and | |
105 | - * ptr->cs_flags has CS_TASK_IS_IN_EXECVE set, it indicates that a | |
106 | - * "struct task_struct" associated with this security context exited | |
107 | - * immediately after do_execve() has failed. | |
108 | - */ | |
109 | - if (ptr->pid && (ptr->cs_flags & CS_TASK_IS_IN_EXECVE)) { | |
110 | - cs_debug_trace("1"); | |
111 | - atomic_dec(&cs_in_execve_tasks); | |
112 | - } | |
113 | - /* | |
114 | - * If this security context was associated with "struct pid", | |
115 | - * drop refcount obtained by get_pid() in cs_find_task_security(). | |
116 | - */ | |
117 | - if (ptr->pid) { | |
118 | - cs_debug_trace("2"); | |
119 | - put_pid(ptr->pid); | |
120 | - } | |
121 | - if (r) { | |
122 | - cs_debug_trace("3"); | |
123 | - kfree(r->handler_path); | |
124 | - kfree(r); | |
125 | - } | |
126 | - kfree(ptr); | |
127 | -} | |
128 | - | |
129 | -/** | |
130 | - * cs_del_security - Release "struct cs_security". | |
131 | - * | |
132 | - * @ptr: Pointer to "struct cs_security". | |
133 | - * | |
134 | - * Returns nothing. | |
135 | - */ | |
136 | -static void cs_del_security(struct cs_security *ptr) | |
137 | -{ | |
138 | - unsigned long flags; | |
139 | - if (ptr == &cs_default_security || ptr == &cs_oom_security) | |
140 | - return; | |
141 | - spin_lock_irqsave(&cs_task_security_list_lock, flags); | |
142 | - list_del_rcu(&ptr->list); | |
143 | - spin_unlock_irqrestore(&cs_task_security_list_lock, flags); | |
144 | - call_rcu(&ptr->rcu, cs_rcu_free); | |
145 | -} | |
146 | - | |
147 | -/** | |
148 | - * cs_add_cred_security - Add "struct cs_security" to list. | |
149 | - * | |
150 | - * @ptr: Pointer to "struct cs_security". | |
151 | - * | |
152 | - * Returns nothing. | |
153 | - */ | |
154 | -static void cs_add_cred_security(struct cs_security *ptr) | |
155 | -{ | |
156 | - unsigned long flags; | |
157 | - struct list_head *list = &cs_cred_security_list | |
158 | - [hash_ptr((void *) ptr->cred, CS_TASK_SECURITY_HASH_BITS)]; | |
159 | -#ifdef CONFIG_CAITSITH_DEBUG | |
160 | - if (ptr->pid) | |
161 | - printk(KERN_INFO "CAITSITH: \"struct cs_security\"->pid != NULL" | |
162 | - "\n"); | |
163 | -#endif | |
164 | - ptr->pid = NULL; | |
165 | - spin_lock_irqsave(&cs_task_security_list_lock, flags); | |
166 | - list_add_rcu(&ptr->list, list); | |
167 | - spin_unlock_irqrestore(&cs_task_security_list_lock, flags); | |
168 | -} | |
169 | - | |
170 | -/** | |
171 | - * cs_task_create - Make snapshot of security context for new task. | |
172 | - * | |
173 | - * @clone_flags: Flags passed to clone(). | |
174 | - * | |
175 | - * Returns 0 on success, negative value otherwise. | |
176 | - */ | |
177 | -static int cs_task_create(unsigned long clone_flags) | |
178 | -{ | |
179 | - struct cs_security *old_security; | |
180 | - struct cs_security *new_security; | |
181 | - struct cred *cred = prepare_creds(); | |
182 | - if (!cred) | |
183 | - return -ENOMEM; | |
184 | - old_security = cs_find_task_security(current); | |
185 | - new_security = cs_find_cred_security(cred); | |
186 | - new_security->cs_domain_info = old_security->cs_domain_info; | |
187 | - new_security->cs_flags = old_security->cs_flags; | |
188 | - return commit_creds(cred); | |
189 | -} | |
190 | - | |
191 | -/** | |
192 | - * cs_cred_prepare - Allocate memory for new credentials. | |
193 | - * | |
194 | - * @new: Pointer to "struct cred". | |
195 | - * @old: Pointer to "struct cred". | |
196 | - * @gfp: Memory allocation flags. | |
197 | - * | |
198 | - * Returns 0 on success, negative value otherwise. | |
199 | - */ | |
200 | -static int cs_cred_prepare(struct cred *new, const struct cred *old, | |
201 | - gfp_t gfp) | |
202 | -{ | |
203 | - int rc1; | |
204 | - /* | |
205 | - * For checking whether reverting domain transition is needed or not. | |
206 | - * | |
207 | - * See cs_find_task_security() for reason. | |
208 | - */ | |
209 | - if (gfp == GFP_KERNEL) | |
210 | - cs_find_task_security(current); | |
211 | - rc1 = cs_copy_cred_security(new, old, gfp); | |
212 | - if (gfp == GFP_KERNEL) | |
213 | - cs_task_security_gc(); | |
214 | - if (original_cred_prepare.cred_prepare) { | |
215 | - const int rc2 = original_cred_prepare.cred_prepare(new, old, | |
216 | - gfp); | |
217 | - if (rc2) { | |
218 | - cs_del_security(cs_find_cred_security(new)); | |
219 | - return rc2; | |
220 | - } | |
221 | - } | |
222 | - return rc1; | |
223 | -} | |
224 | - | |
225 | -/** | |
226 | - * cs_cred_free - Release memory used by credentials. | |
227 | - * | |
228 | - * @cred: Pointer to "struct cred". | |
229 | - * | |
230 | - * Returns nothing. | |
231 | - */ | |
232 | -static void cs_cred_free(struct cred *cred) | |
233 | -{ | |
234 | - if (original_cred_free.cred_free) | |
235 | - original_cred_free.cred_free(cred); | |
236 | - cs_del_security(cs_find_cred_security(cred)); | |
237 | -} | |
238 | - | |
239 | -/** | |
240 | - * cs_alloc_cred_security - Allocate memory for new credentials. | |
241 | - * | |
242 | - * @cred: Pointer to "struct cred". | |
243 | - * @gfp: Memory allocation flags. | |
244 | - * | |
245 | - * Returns 0 on success, negative value otherwise. | |
246 | - */ | |
247 | -static int cs_alloc_cred_security(const struct cred *cred, gfp_t gfp) | |
248 | -{ | |
249 | - struct cs_security *new_security = kzalloc(sizeof(*new_security), | |
250 | - gfp); | |
251 | - if (!new_security) | |
252 | - return -ENOMEM; | |
253 | - new_security->cred = cred; | |
254 | - cs_add_cred_security(new_security); | |
255 | - return 0; | |
256 | -} | |
257 | - | |
258 | -/** | |
259 | - * cs_cred_alloc_blank - Allocate memory for new credentials. | |
260 | - * | |
261 | - * @new: Pointer to "struct cred". | |
262 | - * @gfp: Memory allocation flags. | |
263 | - * | |
264 | - * Returns 0 on success, negative value otherwise. | |
265 | - */ | |
266 | -static int cs_cred_alloc_blank(struct cred *new, gfp_t gfp) | |
267 | -{ | |
268 | - const int rc1 = cs_alloc_cred_security(new, gfp); | |
269 | - if (original_cred_alloc_blank.cred_alloc_blank) { | |
270 | - const int rc2 = original_cred_alloc_blank. | |
271 | - cred_alloc_blank(new, gfp); | |
272 | - if (rc2) { | |
273 | - cs_del_security(cs_find_cred_security(new)); | |
274 | - return rc2; | |
275 | - } | |
276 | - } | |
277 | - return rc1; | |
278 | -} | |
279 | - | |
280 | -/** | |
281 | - * cs_cred_transfer - Transfer "struct cs_security" between credentials. | |
282 | - * | |
283 | - * @new: Pointer to "struct cred". | |
284 | - * @old: Pointer to "struct cred". | |
285 | - * | |
286 | - * Returns nothing. | |
287 | - */ | |
288 | -static void cs_cred_transfer(struct cred *new, const struct cred *old) | |
289 | -{ | |
290 | - struct cs_security *new_security = cs_find_cred_security(new); | |
291 | - struct cs_security *old_security = cs_find_cred_security(old); | |
292 | - if (new_security == &cs_default_security || | |
293 | - new_security == &cs_oom_security || | |
294 | - old_security == &cs_default_security || | |
295 | - old_security == &cs_oom_security) | |
296 | - return; | |
297 | - new_security->cs_flags = old_security->cs_flags; | |
298 | - new_security->cs_domain_info = old_security->cs_domain_info; | |
299 | -} | |
300 | - | |
301 | -/** | |
302 | - * cs_bprm_committing_creds - A hook which is called when do_execve() succeeded. | |
303 | - * | |
304 | - * @bprm: Pointer to "struct linux_binprm". | |
305 | - * | |
306 | - * Returns nothing. | |
307 | - */ | |
308 | -static void cs_bprm_committing_creds(struct linux_binprm *bprm) | |
309 | -{ | |
310 | - struct cs_security *old_security = cs_current_security(); | |
311 | - struct cs_security *new_security; | |
312 | - if (old_security == &cs_default_security || | |
313 | - old_security == &cs_oom_security) | |
314 | - return; | |
315 | - cs_clear_execve(0, old_security); | |
316 | - /* Update current task's cred's domain for future fork(). */ | |
317 | - new_security = cs_find_cred_security(bprm->cred); | |
318 | - new_security->cs_flags = old_security->cs_flags; | |
319 | - new_security->cs_domain_info = old_security->cs_domain_info; | |
320 | -} | |
321 | - | |
322 | -#ifndef CONFIG_CAITSITH_OMIT_USERSPACE_LOADER | |
323 | - | |
324 | -/** | |
325 | - * cs_policy_loader_exists - Check whether /sbin/caitsith-init exists. | |
326 | - * | |
327 | - * Returns true if /sbin/caitsith-init exists, false otherwise. | |
328 | - */ | |
329 | -static _Bool cs_policy_loader_exists(void) | |
330 | -{ | |
331 | - struct path path; | |
332 | - if (kern_path(CONFIG_CAITSITH_POLICY_LOADER, LOOKUP_FOLLOW, &path) | |
333 | - == 0) { | |
334 | - path_put(&path); | |
335 | - return 1; | |
336 | - } | |
337 | - printk(KERN_INFO "Not activating CaitSith as %s does not exist.\n", | |
338 | - CONFIG_CAITSITH_POLICY_LOADER); | |
339 | - return 0; | |
340 | -} | |
341 | - | |
342 | -/** | |
343 | - * cs_load_policy - Run external policy loader to load policy. | |
344 | - * | |
345 | - * @filename: The program about to start. | |
346 | - * | |
347 | - * Returns nothing. | |
348 | - * | |
349 | - * This function checks whether @filename is /sbin/init, and if so | |
350 | - * invoke /sbin/caitsith-init and wait for the termination of | |
351 | - * /sbin/caitsith-init and then continues invocation of /sbin/init. | |
352 | - * /sbin/caitsith-init reads policy files in /etc/caitsith/ directory and | |
353 | - * writes to /proc/caitsith/ interfaces. | |
354 | - */ | |
355 | -static void cs_load_policy(const char *filename) | |
356 | -{ | |
357 | - static _Bool done; | |
358 | - if (done) | |
359 | - return; | |
360 | - if (strcmp(filename, CONFIG_CAITSITH_ACTIVATION_TRIGGER)) | |
361 | - return; | |
362 | - if (!cs_policy_loader_exists()) | |
363 | - return; | |
364 | - done = 1; | |
365 | - { | |
366 | - char *argv[2]; | |
367 | - char *envp[3]; | |
368 | - printk(KERN_INFO "Calling %s to load policy. Please wait.\n", | |
369 | - CONFIG_CAITSITH_POLICY_LOADER); | |
370 | - argv[0] = (char *) CONFIG_CAITSITH_POLICY_LOADER; | |
371 | - argv[1] = NULL; | |
372 | - envp[0] = "HOME=/"; | |
373 | - envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; | |
374 | - envp[2] = NULL; | |
375 | - call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); | |
376 | - } | |
377 | - cs_check_profile(); | |
378 | -} | |
379 | - | |
380 | -#endif | |
381 | - | |
382 | -/** | |
383 | - * cs_bprm_check_security - Check permission for execve(). | |
384 | - * | |
385 | - * @bprm: Pointer to "struct linux_binprm". | |
386 | - * | |
387 | - * Returns 0 on success, negative value otherwise. | |
388 | - */ | |
389 | -static int cs_bprm_check_security(struct linux_binprm *bprm) | |
390 | -{ | |
391 | - struct cs_security *security = cs_current_security(); | |
392 | - int rc; | |
393 | - if (security == &cs_default_security || security == &cs_oom_security) | |
394 | - return -ENOMEM; | |
395 | - if (security->r) | |
396 | - return 0; | |
397 | -#ifndef CONFIG_CAITSITH_OMIT_USERSPACE_LOADER | |
398 | - if (!cs_policy_loaded) | |
399 | - cs_load_policy(bprm->filename); | |
400 | -#endif | |
401 | - rc = cs_start_execve(bprm, &security->r); | |
402 | - if (security->r) | |
403 | - atomic_inc(&cs_in_execve_tasks); | |
404 | - return rc; | |
405 | -} | |
406 | - | |
407 | -/** | |
408 | - * cs_file_open - Check permission for open(). | |
409 | - * | |
410 | - * @f: Pointer to "struct file". | |
411 | - * @cred: Pointer to "struct cred". | |
412 | - * | |
413 | - * Returns 0 on success, negative value otherwise. | |
414 | - */ | |
415 | -static int cs_file_open(struct file *f, const struct cred *cred) | |
416 | -{ | |
417 | - return cs_open_permission(&f->f_path, f->f_flags); | |
418 | -} | |
419 | - | |
420 | -#ifdef CONFIG_SECURITY_PATH | |
421 | - | |
422 | -/** | |
423 | - * cs_path_chown - Check permission for chown()/chgrp(). | |
424 | - * | |
425 | - * @path: Pointer to "struct path". | |
426 | - * @user: User ID. | |
427 | - * @group: Group ID. | |
428 | - * | |
429 | - * Returns 0 on success, negative value otherwise. | |
430 | - */ | |
431 | -static int cs_path_chown(struct path *path, kuid_t user, kgid_t group) | |
432 | -{ | |
433 | - return cs_chown_permission(path, user, group); | |
434 | -} | |
435 | - | |
436 | -/** | |
437 | - * cs_path_chmod - Check permission for chmod(). | |
438 | - * | |
439 | - * @path: Pointer to "struct path". | |
440 | - * @mode: Mode. | |
441 | - * | |
442 | - * Returns 0 on success, negative value otherwise. | |
443 | - */ | |
444 | -static int cs_path_chmod(struct path *path, umode_t mode) | |
445 | -{ | |
446 | - return cs_chmod_permission(path, mode); | |
447 | -} | |
448 | - | |
449 | -/** | |
450 | - * cs_path_chroot - Check permission for chroot(). | |
451 | - * | |
452 | - * @path: Pointer to "struct path". | |
453 | - * | |
454 | - * Returns 0 on success, negative value otherwise. | |
455 | - */ | |
456 | -static int cs_path_chroot(struct path *path) | |
457 | -{ | |
458 | - return cs_chroot_permission(path); | |
459 | -} | |
460 | - | |
461 | -/** | |
462 | - * cs_path_truncate - Check permission for truncate(). | |
463 | - * | |
464 | - * @path: Pointer to "struct path". | |
465 | - * | |
466 | - * Returns 0 on success, negative value otherwise. | |
467 | - */ | |
468 | -static int cs_path_truncate(struct path *path) | |
469 | -{ | |
470 | - return cs_truncate_permission(path); | |
471 | -} | |
472 | - | |
473 | -#else | |
474 | - | |
475 | -/** | |
476 | - * cs_inode_setattr - Check permission for chown()/chgrp()/chmod()/truncate(). | |
477 | - * | |
478 | - * @dentry: Pointer to "struct dentry". | |
479 | - * @attr: Pointer to "struct iattr". | |
480 | - * | |
481 | - * Returns 0 on success, negative value otherwise. | |
482 | - */ | |
483 | -static int cs_inode_setattr(struct dentry *dentry, struct iattr *attr) | |
484 | -{ | |
485 | - int rc = 0; | |
486 | - struct path path = { NULL, dentry }; | |
487 | - if (attr->ia_valid & ATTR_UID) | |
488 | - rc = cs_chown_permission(&path, attr->ia_uid, INVALID_GID); | |
489 | - if (!rc && (attr->ia_valid & ATTR_GID)) | |
490 | - rc = cs_chown_permission(&path, INVALID_UID, attr->ia_gid); | |
491 | - if (!rc && (attr->ia_valid & ATTR_MODE)) | |
492 | - rc = cs_chmod_permission(&path, attr->ia_mode); | |
493 | - if (!rc && (attr->ia_valid & ATTR_SIZE)) | |
494 | - rc = cs_truncate_permission(&path); | |
495 | - return rc; | |
496 | -} | |
497 | - | |
498 | -#endif | |
499 | - | |
500 | -/** | |
501 | - * cs_inode_getattr - Check permission for stat(). | |
502 | - * | |
503 | - * @path: Pointer to "struct path". | |
504 | - * | |
505 | - * Returns 0 on success, negative value otherwise. | |
506 | - */ | |
507 | -static int cs_inode_getattr(const struct path *path) | |
508 | -{ | |
509 | - return cs_getattr_permission(path); | |
510 | -} | |
511 | - | |
512 | -#ifdef CONFIG_SECURITY_PATH | |
513 | - | |
514 | -/** | |
515 | - * cs_path_mknod - Check permission for mknod(). | |
516 | - * | |
517 | - * @dir: Pointer to "struct path". | |
518 | - * @dentry: Pointer to "struct dentry". | |
519 | - * @mode: Create mode. | |
520 | - * @dev: Device major/minor number. | |
521 | - * | |
522 | - * Returns 0 on success, negative value otherwise. | |
523 | - */ | |
524 | -static int cs_path_mknod(struct path *dir, struct dentry *dentry, | |
525 | - umode_t mode, unsigned int dev) | |
526 | -{ | |
527 | - struct path path = { dir->mnt, dentry }; | |
528 | - return cs_mknod_permission(&path, mode, dev); | |
529 | -} | |
530 | - | |
531 | -/** | |
532 | - * cs_path_mkdir - Check permission for mkdir(). | |
533 | - * | |
534 | - * @dir: Pointer to "struct path". | |
535 | - * @dentry: Pointer to "struct dentry". | |
536 | - * @mode: Create mode. | |
537 | - * | |
538 | - * Returns 0 on success, negative value otherwise. | |
539 | - */ | |
540 | -static int cs_path_mkdir(struct path *dir, struct dentry *dentry, | |
541 | - umode_t mode) | |
542 | -{ | |
543 | - struct path path = { dir->mnt, dentry }; | |
544 | - return cs_mkdir_permission(&path, mode); | |
545 | -} | |
546 | - | |
547 | -/** | |
548 | - * cs_path_rmdir - Check permission for rmdir(). | |
549 | - * | |
550 | - * @dir: Pointer to "struct path". | |
551 | - * @dentry: Pointer to "struct dentry". | |
552 | - * | |
553 | - * Returns 0 on success, negative value otherwise. | |
554 | - */ | |
555 | -static int cs_path_rmdir(struct path *dir, struct dentry *dentry) | |
556 | -{ | |
557 | - struct path path = { dir->mnt, dentry }; | |
558 | - return cs_rmdir_permission(&path); | |
559 | -} | |
560 | - | |
561 | -/** | |
562 | - * cs_path_unlink - Check permission for unlink(). | |
563 | - * | |
564 | - * @dir: Pointer to "struct path". | |
565 | - * @dentry: Pointer to "struct dentry". | |
566 | - * | |
567 | - * Returns 0 on success, negative value otherwise. | |
568 | - */ | |
569 | -static int cs_path_unlink(struct path *dir, struct dentry *dentry) | |
570 | -{ | |
571 | - struct path path = { dir->mnt, dentry }; | |
572 | - return cs_unlink_permission(&path); | |
573 | -} | |
574 | - | |
575 | -/** | |
576 | - * cs_path_symlink - Check permission for symlink(). | |
577 | - * | |
578 | - * @dir: Pointer to "struct path". | |
579 | - * @dentry: Pointer to "struct dentry". | |
580 | - * @old_name: Content of symbolic link. | |
581 | - * | |
582 | - * Returns 0 on success, negative value otherwise. | |
583 | - */ | |
584 | -static int cs_path_symlink(struct path *dir, struct dentry *dentry, | |
585 | - const char *old_name) | |
586 | -{ | |
587 | - struct path path = { dir->mnt, dentry }; | |
588 | - return cs_symlink_permission(&path, old_name); | |
589 | -} | |
590 | - | |
591 | -/** | |
592 | - * cs_path_rename - Check permission for rename(). | |
593 | - * | |
594 | - * @old_dir: Pointer to "struct path". | |
595 | - * @old_dentry: Pointer to "struct dentry". | |
596 | - * @new_dir: Pointer to "struct path". | |
597 | - * @new_dentry: Pointer to "struct dentry". | |
598 | - * | |
599 | - * Returns 0 on success, negative value otherwise. | |
600 | - */ | |
601 | -static int cs_path_rename(struct path *old_dir, struct dentry *old_dentry, | |
602 | - struct path *new_dir, struct dentry *new_dentry) | |
603 | -{ | |
604 | - struct path old = { old_dir->mnt, old_dentry }; | |
605 | - struct path new = { new_dir->mnt, new_dentry }; | |
606 | - return cs_rename_permission(&old, &new); | |
607 | -} | |
608 | - | |
609 | -/** | |
610 | - * cs_path_link - Check permission for link(). | |
611 | - * | |
612 | - * @old_dentry: Pointer to "struct dentry". | |
613 | - * @new_dir: Pointer to "struct path". | |
614 | - * @new_dentry: Pointer to "struct dentry". | |
615 | - * | |
616 | - * Returns 0 on success, negative value otherwise. | |
617 | - */ | |
618 | -static int cs_path_link(struct dentry *old_dentry, struct path *new_dir, | |
619 | - struct dentry *new_dentry) | |
620 | -{ | |
621 | - struct path old = { new_dir->mnt, old_dentry }; | |
622 | - struct path new = { new_dir->mnt, new_dentry }; | |
623 | - return cs_link_permission(&old, &new); | |
624 | -} | |
625 | - | |
626 | -#else | |
627 | - | |
628 | -/** | |
629 | - * cs_inode_mknod - Check permission for mknod(). | |
630 | - * | |
631 | - * @dir: Pointer to "struct inode". | |
632 | - * @dentry: Pointer to "struct dentry". | |
633 | - * @mode: Create mode. | |
634 | - * @dev: Device major/minor number. | |
635 | - * | |
636 | - * Returns 0 on success, negative value otherwise. | |
637 | - */ | |
638 | -static int cs_inode_mknod(struct inode *dir, struct dentry *dentry, | |
639 | - umode_t mode, dev_t dev) | |
640 | -{ | |
641 | - struct path path = { NULL, dentry }; | |
642 | - return cs_mknod_permission(&path, mode, dev); | |
643 | -} | |
644 | - | |
645 | -/** | |
646 | - * cs_inode_mkdir - Check permission for mkdir(). | |
647 | - * | |
648 | - * @dir: Pointer to "struct inode". | |
649 | - * @dentry: Pointer to "struct dentry". | |
650 | - * @mode: Create mode. | |
651 | - * | |
652 | - * Returns 0 on success, negative value otherwise. | |
653 | - */ | |
654 | -static int cs_inode_mkdir(struct inode *dir, struct dentry *dentry, | |
655 | - umode_t mode) | |
656 | -{ | |
657 | - struct path path = { NULL, dentry }; | |
658 | - return cs_mkdir_permission(&path, mode); | |
659 | -} | |
660 | - | |
661 | -/** | |
662 | - * cs_inode_rmdir - Check permission for rmdir(). | |
663 | - * | |
664 | - * @dir: Pointer to "struct inode". | |
665 | - * @dentry: Pointer to "struct dentry". | |
666 | - * | |
667 | - * Returns 0 on success, negative value otherwise. | |
668 | - */ | |
669 | -static int cs_inode_rmdir(struct inode *dir, struct dentry *dentry) | |
670 | -{ | |
671 | - struct path path = { NULL, dentry }; | |
672 | - return cs_rmdir_permission(&path); | |
673 | -} | |
674 | - | |
675 | -/** | |
676 | - * cs_inode_unlink - Check permission for unlink(). | |
677 | - * | |
678 | - * @dir: Pointer to "struct inode". | |
679 | - * @dentry: Pointer to "struct dentry". | |
680 | - * | |
681 | - * Returns 0 on success, negative value otherwise. | |
682 | - */ | |
683 | -static int cs_inode_unlink(struct inode *dir, struct dentry *dentry) | |
684 | -{ | |
685 | - struct path path = { NULL, dentry }; | |
686 | - return cs_unlink_permission(&path); | |
687 | -} | |
688 | - | |
689 | -/** | |
690 | - * cs_inode_symlink - Check permission for symlink(). | |
691 | - * | |
692 | - * @dir: Pointer to "struct inode". | |
693 | - * @dentry: Pointer to "struct dentry". | |
694 | - * @old_name: Content of symbolic link. | |
695 | - * | |
696 | - * Returns 0 on success, negative value otherwise. | |
697 | - */ | |
698 | -static int cs_inode_symlink(struct inode *dir, struct dentry *dentry, | |
699 | - const char *old_name) | |
700 | -{ | |
701 | - struct path path = { NULL, dentry }; | |
702 | - return cs_symlink_permission(&path, old_name); | |
703 | -} | |
704 | - | |
705 | -/** | |
706 | - * cs_inode_rename - Check permission for rename(). | |
707 | - * | |
708 | - * @old_dir: Pointer to "struct inode". | |
709 | - * @old_dentry: Pointer to "struct dentry". | |
710 | - * @new_dir: Pointer to "struct inode". | |
711 | - * @new_dentry: Pointer to "struct dentry". | |
712 | - * | |
713 | - * Returns 0 on success, negative value otherwise. | |
714 | - */ | |
715 | -static int cs_inode_rename(struct inode *old_dir, struct dentry *old_dentry, | |
716 | - struct inode *new_dir, struct dentry *new_dentry) | |
717 | -{ | |
718 | - struct path old = { NULL, old_dentry }; | |
719 | - struct path new = { NULL, new_dentry }; | |
720 | - return cs_rename_permission(&old, &new); | |
721 | -} | |
722 | - | |
723 | -/** | |
724 | - * cs_inode_link - Check permission for link(). | |
725 | - * | |
726 | - * @old_dentry: Pointer to "struct dentry". | |
727 | - * @dir: Pointer to "struct inode". | |
728 | - * @new_dentry: Pointer to "struct dentry". | |
729 | - * | |
730 | - * Returns 0 on success, negative value otherwise. | |
731 | - */ | |
732 | -static int cs_inode_link(struct dentry *old_dentry, struct inode *dir, | |
733 | - struct dentry *new_dentry) | |
734 | -{ | |
735 | - struct path old = { NULL, old_dentry }; | |
736 | - struct path new = { NULL, new_dentry }; | |
737 | - return cs_link_permission(&old, &new); | |
738 | -} | |
739 | - | |
740 | -/** | |
741 | - * cs_inode_create - Check permission for creat(). | |
742 | - * | |
743 | - * @dir: Pointer to "struct inode". | |
744 | - * @dentry: Pointer to "struct dentry". | |
745 | - * @mode: Create mode. | |
746 | - * | |
747 | - * Returns 0 on success, negative value otherwise. | |
748 | - */ | |
749 | -static int cs_inode_create(struct inode *dir, struct dentry *dentry, | |
750 | - umode_t mode) | |
751 | -{ | |
752 | - struct path path = { NULL, dentry }; | |
753 | - return cs_mknod_permission(&path, mode, 0); | |
754 | -} | |
755 | - | |
756 | -#endif | |
757 | - | |
758 | -#ifdef CONFIG_SECURITY_NETWORK | |
759 | - | |
760 | -#include <net/sock.h> | |
761 | - | |
762 | -/* Structure for remembering an accept()ed socket's status. */ | |
763 | -struct cs_socket_tag { | |
764 | - struct list_head list; | |
765 | - struct inode *inode; | |
766 | - int status; | |
767 | - struct rcu_head rcu; | |
768 | -}; | |
769 | - | |
770 | -/* | |
771 | - * List for managing accept()ed sockets. | |
772 | - * Since we don't need to keep an accept()ed socket into this list after | |
773 | - * once the permission was granted, the number of entries in this list is | |
774 | - * likely small. Therefore, we don't use hash tables. | |
775 | - */ | |
776 | -static LIST_HEAD(cs_accepted_socket_list); | |
777 | -/* Lock for protecting cs_accepted_socket_list . */ | |
778 | -static DEFINE_SPINLOCK(cs_accepted_socket_list_lock); | |
779 | - | |
780 | -/** | |
781 | - * cs_socket_rcu_free - RCU callback for releasing "struct cs_socket_tag". | |
782 | - * | |
783 | - * @rcu: Pointer to "struct rcu_head". | |
784 | - * | |
785 | - * Returns nothing. | |
786 | - */ | |
787 | -static void cs_socket_rcu_free(struct rcu_head *rcu) | |
788 | -{ | |
789 | - struct cs_socket_tag *ptr = container_of(rcu, typeof(*ptr), rcu); | |
790 | - kfree(ptr); | |
791 | -} | |
792 | - | |
793 | -/** | |
794 | - * cs_update_socket_tag - Update tag associated with accept()ed sockets. | |
795 | - * | |
796 | - * @inode: Pointer to "struct inode". | |
797 | - * @status: New status. | |
798 | - * | |
799 | - * Returns nothing. | |
800 | - * | |
801 | - * If @status == 0, memory for that socket will be released after RCU grace | |
802 | - * period. | |
803 | - */ | |
804 | -static void cs_update_socket_tag(struct inode *inode, int status) | |
805 | -{ | |
806 | - struct cs_socket_tag *ptr; | |
807 | - /* | |
808 | - * Protect whole section because multiple threads may call this | |
809 | - * function with same "sock" via cs_validate_socket(). | |
810 | - */ | |
811 | - spin_lock(&cs_accepted_socket_list_lock); | |
812 | - rcu_read_lock(); | |
813 | - list_for_each_entry_rcu(ptr, &cs_accepted_socket_list, list) { | |
814 | - if (ptr->inode != inode) | |
815 | - continue; | |
816 | - ptr->status = status; | |
817 | - if (status) | |
818 | - break; | |
819 | - list_del_rcu(&ptr->list); | |
820 | - call_rcu(&ptr->rcu, cs_socket_rcu_free); | |
821 | - break; | |
822 | - } | |
823 | - rcu_read_unlock(); | |
824 | - spin_unlock(&cs_accepted_socket_list_lock); | |
825 | -} | |
826 | - | |
827 | -/** | |
828 | - * cs_validate_socket - Check post accept() permission if needed. | |
829 | - * | |
830 | - * @sock: Pointer to "struct socket". | |
831 | - * | |
832 | - * Returns 0 on success, negative value otherwise. | |
833 | - */ | |
834 | -static int cs_validate_socket(struct socket *sock) | |
835 | -{ | |
836 | - struct inode *inode = SOCK_INODE(sock); | |
837 | - struct cs_socket_tag *ptr; | |
838 | - int ret = 0; | |
839 | - rcu_read_lock(); | |
840 | - list_for_each_entry_rcu(ptr, &cs_accepted_socket_list, list) { | |
841 | - if (ptr->inode != inode) | |
842 | - continue; | |
843 | - ret = ptr->status; | |
844 | - break; | |
845 | - } | |
846 | - rcu_read_unlock(); | |
847 | - if (ret <= 0) | |
848 | - /* | |
849 | - * This socket is not an accept()ed socket or this socket is | |
850 | - * an accept()ed socket and post accept() permission is done. | |
851 | - */ | |
852 | - return ret; | |
853 | - /* | |
854 | - * Check post accept() permission now. | |
855 | - * | |
856 | - * Strictly speaking, we need to pass both listen()ing socket and | |
857 | - * accept()ed socket to __cs_socket_post_accept_permission(). | |
858 | - * But since socket's family and type are same for both sockets, | |
859 | - * passing the accept()ed socket in place for the listen()ing socket | |
860 | - * will work. | |
861 | - */ | |
862 | - ret = cs_socket_post_accept_permission(sock, sock); | |
863 | - /* | |
864 | - * If permission was granted, we forget that this is an accept()ed | |
865 | - * socket. Otherwise, we remember that this socket needs to return | |
866 | - * error for subsequent socketcalls. | |
867 | - */ | |
868 | - cs_update_socket_tag(inode, ret); | |
869 | - return ret; | |
870 | -} | |
871 | - | |
872 | -/** | |
873 | - * cs_socket_accept - Check permission for accept(). | |
874 | - * | |
875 | - * @sock: Pointer to "struct socket". | |
876 | - * @newsock: Pointer to "struct socket". | |
877 | - * | |
878 | - * Returns 0 on success, negative value otherwise. | |
879 | - * | |
880 | - * This hook is used for setting up environment for doing post accept() | |
881 | - * permission check. If dereferencing sock->ops->something() were ordered by | |
882 | - * rcu_dereference(), we could replace sock->ops with "a copy of original | |
883 | - * sock->ops with modified sock->ops->accept()" using rcu_assign_pointer() | |
884 | - * in order to do post accept() permission check before returning to userspace. | |
885 | - * If we make the copy in security_socket_post_create(), it would be possible | |
886 | - * to safely replace sock->ops here, but we don't do so because we don't want | |
887 | - * to allocate memory for sockets which do not call sock->ops->accept(). | |
888 | - * Therefore, we do post accept() permission check upon next socket syscalls | |
889 | - * rather than between sock->ops->accept() and returning to userspace. | |
890 | - * This means that if a socket was close()d before calling some socket | |
891 | - * syscalls, post accept() permission check will not be done. | |
892 | - */ | |
893 | -static int cs_socket_accept(struct socket *sock, struct socket *newsock) | |
894 | -{ | |
895 | - struct cs_socket_tag *ptr; | |
896 | - const int rc = cs_validate_socket(sock); | |
897 | - if (rc < 0) | |
898 | - return rc; | |
899 | - ptr = kzalloc(sizeof(*ptr), GFP_KERNEL); | |
900 | - if (!ptr) | |
901 | - return -ENOMEM; | |
902 | - /* | |
903 | - * Subsequent LSM hooks will receive "newsock". Therefore, I mark | |
904 | - * "newsock" as "an accept()ed socket but post accept() permission | |
905 | - * check is not done yet" by allocating memory using inode of the | |
906 | - * "newsock" as a search key. | |
907 | - */ | |
908 | - ptr->inode = SOCK_INODE(newsock); | |
909 | - ptr->status = 1; /* Check post accept() permission later. */ | |
910 | - spin_lock(&cs_accepted_socket_list_lock); | |
911 | - list_add_tail_rcu(&ptr->list, &cs_accepted_socket_list); | |
912 | - spin_unlock(&cs_accepted_socket_list_lock); | |
913 | - return 0; | |
914 | -} | |
915 | - | |
916 | -/** | |
917 | - * cs_socket_listen - Check permission for listen(). | |
918 | - * | |
919 | - * @sock: Pointer to "struct socket". | |
920 | - * @backlog: Backlog parameter. | |
921 | - * | |
922 | - * Returns 0 on success, negative value otherwise. | |
923 | - */ | |
924 | -static int cs_socket_listen(struct socket *sock, int backlog) | |
925 | -{ | |
926 | - const int rc = cs_validate_socket(sock); | |
927 | - if (rc < 0) | |
928 | - return rc; | |
929 | - return cs_socket_listen_permission(sock); | |
930 | -} | |
931 | - | |
932 | -/** | |
933 | - * cs_socket_connect - Check permission for connect(). | |
934 | - * | |
935 | - * @sock: Pointer to "struct socket". | |
936 | - * @addr: Pointer to "struct sockaddr". | |
937 | - * @addr_len: Size of @addr. | |
938 | - * | |
939 | - * Returns 0 on success, negative value otherwise. | |
940 | - */ | |
941 | -static int cs_socket_connect(struct socket *sock, struct sockaddr *addr, | |
942 | - int addr_len) | |
943 | -{ | |
944 | - const int rc = cs_validate_socket(sock); | |
945 | - if (rc < 0) | |
946 | - return rc; | |
947 | - return cs_socket_connect_permission(sock, addr, addr_len); | |
948 | -} | |
949 | - | |
950 | -/** | |
951 | - * cs_socket_bind - Check permission for bind(). | |
952 | - * | |
953 | - * @sock: Pointer to "struct socket". | |
954 | - * @addr: Pointer to "struct sockaddr". | |
955 | - * @addr_len: Size of @addr. | |
956 | - * | |
957 | - * Returns 0 on success, negative value otherwise. | |
958 | - */ | |
959 | -static int cs_socket_bind(struct socket *sock, struct sockaddr *addr, | |
960 | - int addr_len) | |
961 | -{ | |
962 | - const int rc = cs_validate_socket(sock); | |
963 | - if (rc < 0) | |
964 | - return rc; | |
965 | - return cs_socket_bind_permission(sock, addr, addr_len); | |
966 | -} | |
967 | - | |
968 | -/** | |
969 | - * cs_socket_sendmsg - Check permission for sendmsg(). | |
970 | - * | |
971 | - * @sock: Pointer to "struct socket". | |
972 | - * @msg: Pointer to "struct msghdr". | |
973 | - * @size: Size of message. | |
974 | - * | |
975 | - * Returns 0 on success, negative value otherwise. | |
976 | - */ | |
977 | -static int cs_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |
978 | - int size) | |
979 | -{ | |
980 | - const int rc = cs_validate_socket(sock); | |
981 | - if (rc < 0) | |
982 | - return rc; | |
983 | - return cs_socket_sendmsg_permission(sock, msg, size); | |
984 | -} | |
985 | - | |
986 | -/** | |
987 | - * cs_socket_recvmsg - Check permission for recvmsg(). | |
988 | - * | |
989 | - * @sock: Pointer to "struct socket". | |
990 | - * @msg: Pointer to "struct msghdr". | |
991 | - * @size: Size of message. | |
992 | - * @flags: Flags. | |
993 | - * | |
994 | - * Returns 0 on success, negative value otherwise. | |
995 | - */ | |
996 | -static int cs_socket_recvmsg(struct socket *sock, struct msghdr *msg, | |
997 | - int size, int flags) | |
998 | -{ | |
999 | - return cs_validate_socket(sock); | |
1000 | -} | |
1001 | - | |
1002 | -/** | |
1003 | - * cs_socket_getsockname - Check permission for getsockname(). | |
1004 | - * | |
1005 | - * @sock: Pointer to "struct socket". | |
1006 | - * | |
1007 | - * Returns 0 on success, negative value otherwise. | |
1008 | - */ | |
1009 | -static int cs_socket_getsockname(struct socket *sock) | |
1010 | -{ | |
1011 | - return cs_validate_socket(sock); | |
1012 | -} | |
1013 | - | |
1014 | -/** | |
1015 | - * cs_socket_getpeername - Check permission for getpeername(). | |
1016 | - * | |
1017 | - * @sock: Pointer to "struct socket". | |
1018 | - * | |
1019 | - * Returns 0 on success, negative value otherwise. | |
1020 | - */ | |
1021 | -static int cs_socket_getpeername(struct socket *sock) | |
1022 | -{ | |
1023 | - return cs_validate_socket(sock); | |
1024 | -} | |
1025 | - | |
1026 | -/** | |
1027 | - * cs_socket_getsockopt - Check permission for getsockopt(). | |
1028 | - * | |
1029 | - * @sock: Pointer to "struct socket". | |
1030 | - * @level: Level. | |
1031 | - * @optname: Option's name, | |
1032 | - * | |
1033 | - * Returns 0 on success, negative value otherwise. | |
1034 | - */ | |
1035 | -static int cs_socket_getsockopt(struct socket *sock, int level, int optname) | |
1036 | -{ | |
1037 | - return cs_validate_socket(sock); | |
1038 | -} | |
1039 | - | |
1040 | -/** | |
1041 | - * cs_socket_setsockopt - Check permission for setsockopt(). | |
1042 | - * | |
1043 | - * @sock: Pointer to "struct socket". | |
1044 | - * @level: Level. | |
1045 | - * @optname: Option's name, | |
1046 | - * | |
1047 | - * Returns 0 on success, negative value otherwise. | |
1048 | - */ | |
1049 | -static int cs_socket_setsockopt(struct socket *sock, int level, int optname) | |
1050 | -{ | |
1051 | - return cs_validate_socket(sock); | |
1052 | -} | |
1053 | - | |
1054 | -/** | |
1055 | - * cs_socket_shutdown - Check permission for shutdown(). | |
1056 | - * | |
1057 | - * @sock: Pointer to "struct socket". | |
1058 | - * @how: Shutdown mode. | |
1059 | - * | |
1060 | - * Returns 0 on success, negative value otherwise. | |
1061 | - */ | |
1062 | -static int cs_socket_shutdown(struct socket *sock, int how) | |
1063 | -{ | |
1064 | - return cs_validate_socket(sock); | |
1065 | -} | |
1066 | - | |
1067 | -#define SOCKFS_MAGIC 0x534F434B | |
1068 | - | |
1069 | -/** | |
1070 | - * cs_inode_free_security - Release memory associated with an inode. | |
1071 | - * | |
1072 | - * @inode: Pointer to "struct inode". | |
1073 | - * | |
1074 | - * Returns nothing. | |
1075 | - * | |
1076 | - * We use this hook for releasing memory associated with an accept()ed socket. | |
1077 | - */ | |
1078 | -static void cs_inode_free_security(struct inode *inode) | |
1079 | -{ | |
1080 | - if (inode->i_sb && inode->i_sb->s_magic == SOCKFS_MAGIC) | |
1081 | - cs_update_socket_tag(inode, 0); | |
1082 | -} | |
1083 | - | |
1084 | -#endif | |
1085 | - | |
1086 | -/** | |
1087 | - * cs_sb_pivotroot - Check permission for pivot_root(). | |
1088 | - * | |
1089 | - * @old_path: Pointer to "struct path". | |
1090 | - * @new_path: Pointer to "struct path". | |
1091 | - * | |
1092 | - * Returns 0 on success, negative value otherwise. | |
1093 | - */ | |
1094 | -static int cs_sb_pivotroot(struct path *old_path, struct path *new_path) | |
1095 | -{ | |
1096 | - return cs_pivot_root_permission(old_path, new_path); | |
1097 | -} | |
1098 | - | |
1099 | -/** | |
1100 | - * cs_sb_mount - Check permission for mount(). | |
1101 | - * | |
1102 | - * @dev_name: Name of device file. | |
1103 | - * @path: Pointer to "struct path". | |
1104 | - * @type: Name of filesystem type. Maybe NULL. | |
1105 | - * @flags: Mount options. | |
1106 | - * @data_page: Optional data. Maybe NULL. | |
1107 | - * | |
1108 | - * Returns 0 on success, negative value otherwise. | |
1109 | - */ | |
1110 | -static int cs_sb_mount(const char *dev_name, struct path *path, | |
1111 | - const char *type, unsigned long flags, void *data_page) | |
1112 | -{ | |
1113 | - return cs_mount_permission(dev_name, path, type, flags, data_page); | |
1114 | -} | |
1115 | - | |
1116 | -/** | |
1117 | - * cs_sb_umount - Check permission for umount(). | |
1118 | - * | |
1119 | - * @mnt: Pointer to "struct vfsmount". | |
1120 | - * @flags: Unmount flags. | |
1121 | - * | |
1122 | - * Returns 0 on success, negative value otherwise. | |
1123 | - */ | |
1124 | -static int cs_sb_umount(struct vfsmount *mnt, int flags) | |
1125 | -{ | |
1126 | - struct path path = { mnt, mnt->mnt_root }; | |
1127 | - return cs_umount_permission(&path, flags); | |
1128 | -} | |
1129 | - | |
1130 | -/** | |
1131 | - * cs_file_fcntl - Check permission for fcntl(). | |
1132 | - * | |
1133 | - * @file: Pointer to "struct file". | |
1134 | - * @cmd: Command number. | |
1135 | - * @arg: Value for @cmd. | |
1136 | - * | |
1137 | - * Returns 0 on success, negative value otherwise. | |
1138 | - */ | |
1139 | -static int cs_file_fcntl(struct file *file, unsigned int cmd, | |
1140 | - unsigned long arg) | |
1141 | -{ | |
1142 | - return cs_fcntl_permission(file, cmd, arg); | |
1143 | -} | |
1144 | - | |
1145 | -/** | |
1146 | - * cs_file_ioctl - Check permission for ioctl(). | |
1147 | - * | |
1148 | - * @filp: Pointer to "struct file". | |
1149 | - * @cmd: Command number. | |
1150 | - * @arg: Value for @cmd. | |
1151 | - * | |
1152 | - * Returns 0 on success, negative value otherwise. | |
1153 | - */ | |
1154 | -static int cs_file_ioctl(struct file *filp, unsigned int cmd, | |
1155 | - unsigned long arg) | |
1156 | -{ | |
1157 | - return cs_ioctl_permission(filp, cmd, arg); | |
1158 | -} | |
1159 | - | |
1160 | -#define MY_HOOK_INIT(HEAD, HOOK) \ | |
1161 | - { .head = &probe_dummy_security_hook_heads.HEAD, \ | |
1162 | - .hook = { .HEAD = HOOK } } | |
1163 | - | |
1164 | -static struct security_hook_list caitsith_hooks[] = { | |
1165 | - /* Security context allocator. */ | |
1166 | - MY_HOOK_INIT(cred_free, cs_cred_free), | |
1167 | - MY_HOOK_INIT(cred_prepare, cs_cred_prepare), | |
1168 | - MY_HOOK_INIT(cred_alloc_blank, cs_cred_alloc_blank), | |
1169 | - MY_HOOK_INIT(cred_transfer, cs_cred_transfer), | |
1170 | - MY_HOOK_INIT(task_create, cs_task_create), | |
1171 | - /* Security context updater for successful execve(). */ | |
1172 | - MY_HOOK_INIT(bprm_check_security, cs_bprm_check_security), | |
1173 | - MY_HOOK_INIT(bprm_committing_creds, cs_bprm_committing_creds), | |
1174 | - /* Various permission checker. */ | |
1175 | - MY_HOOK_INIT(file_open, cs_file_open), | |
1176 | - MY_HOOK_INIT(file_fcntl, cs_file_fcntl), | |
1177 | - MY_HOOK_INIT(file_ioctl, cs_file_ioctl), | |
1178 | - MY_HOOK_INIT(sb_pivotroot, cs_sb_pivotroot), | |
1179 | - MY_HOOK_INIT(sb_mount, cs_sb_mount), | |
1180 | - MY_HOOK_INIT(sb_umount, cs_sb_umount), | |
1181 | -#ifdef CONFIG_SECURITY_PATH | |
1182 | - MY_HOOK_INIT(path_mknod, cs_path_mknod), | |
1183 | - MY_HOOK_INIT(path_mkdir, cs_path_mkdir), | |
1184 | - MY_HOOK_INIT(path_rmdir, cs_path_rmdir), | |
1185 | - MY_HOOK_INIT(path_unlink, cs_path_unlink), | |
1186 | - MY_HOOK_INIT(path_symlink, cs_path_symlink), | |
1187 | - MY_HOOK_INIT(path_rename, cs_path_rename), | |
1188 | - MY_HOOK_INIT(path_link, cs_path_link), | |
1189 | - MY_HOOK_INIT(path_truncate, cs_path_truncate), | |
1190 | - MY_HOOK_INIT(path_chmod, cs_path_chmod), | |
1191 | - MY_HOOK_INIT(path_chown, cs_path_chown), | |
1192 | - MY_HOOK_INIT(path_chroot, cs_path_chroot), | |
1193 | -#else | |
1194 | - MY_HOOK_INIT(inode_mknod, cs_inode_mknod), | |
1195 | - MY_HOOK_INIT(inode_mkdir, cs_inode_mkdir), | |
1196 | - MY_HOOK_INIT(inode_rmdir, cs_inode_rmdir), | |
1197 | - MY_HOOK_INIT(inode_unlink, cs_inode_unlink), | |
1198 | - MY_HOOK_INIT(inode_symlink, cs_inode_symlink), | |
1199 | - MY_HOOK_INIT(inode_rename, cs_inode_rename), | |
1200 | - MY_HOOK_INIT(inode_link, cs_inode_link), | |
1201 | - MY_HOOK_INIT(inode_create, cs_inode_create), | |
1202 | - MY_HOOK_INIT(inode_setattr, cs_inode_setattr), | |
1203 | -#endif | |
1204 | - MY_HOOK_INIT(inode_getattr, cs_inode_getattr), | |
1205 | -#ifdef CONFIG_SECURITY_NETWORK | |
1206 | - MY_HOOK_INIT(socket_bind, cs_socket_bind), | |
1207 | - MY_HOOK_INIT(socket_connect, cs_socket_connect), | |
1208 | - MY_HOOK_INIT(socket_listen, cs_socket_listen), | |
1209 | - MY_HOOK_INIT(socket_sendmsg, cs_socket_sendmsg), | |
1210 | - MY_HOOK_INIT(socket_recvmsg, cs_socket_recvmsg), | |
1211 | - MY_HOOK_INIT(socket_getsockname, cs_socket_getsockname), | |
1212 | - MY_HOOK_INIT(socket_getpeername, cs_socket_getpeername), | |
1213 | - MY_HOOK_INIT(socket_getsockopt, cs_socket_getsockopt), | |
1214 | - MY_HOOK_INIT(socket_setsockopt, cs_socket_setsockopt), | |
1215 | - MY_HOOK_INIT(socket_shutdown, cs_socket_shutdown), | |
1216 | - MY_HOOK_INIT(socket_accept, cs_socket_accept), | |
1217 | - MY_HOOK_INIT(inode_free_security, cs_inode_free_security), | |
1218 | -#endif | |
1219 | -}; | |
1220 | - | |
1221 | -static inline void add_hook(struct security_hook_list *hook) | |
1222 | -{ | |
1223 | - list_add_tail_rcu(&hook->list, hook->head); | |
1224 | -} | |
1225 | - | |
1226 | -static void __init swap_hook(struct security_hook_list *hook, | |
1227 | - union security_list_options *original) | |
1228 | -{ | |
1229 | - struct list_head *list = hook->head; | |
1230 | - if (list_empty(list)) { | |
1231 | - add_hook(hook); | |
1232 | - } else { | |
1233 | - struct security_hook_list *shp = | |
1234 | - list_last_entry(list, struct security_hook_list, list); | |
1235 | - *original = shp->hook; | |
1236 | - smp_wmb(); | |
1237 | - shp->hook = hook->hook; | |
1238 | - } | |
1239 | -} | |
1240 | - | |
1241 | -/** | |
1242 | - * cs_init - Initialize this module. | |
1243 | - * | |
1244 | - * Returns 0 on success, negative value otherwise. | |
1245 | - */ | |
1246 | -static int __init cs_init(void) | |
1247 | -{ | |
1248 | - int idx; | |
1249 | - struct security_hook_heads *hooks = probe_security_hook_heads(); | |
1250 | - if (!hooks) | |
1251 | - goto out; | |
1252 | - for (idx = 0; idx < ARRAY_SIZE(caitsith_hooks); idx++) | |
1253 | - caitsith_hooks[idx].head = ((void *) hooks) | |
1254 | - + ((unsigned long) caitsith_hooks[idx].head) | |
1255 | - - ((unsigned long) &probe_dummy_security_hook_heads); | |
1256 | - caitsith_exports.find_task_by_vpid = probe_find_task_by_vpid(); | |
1257 | - if (!caitsith_exports.find_task_by_vpid) | |
1258 | - goto out; | |
1259 | - caitsith_exports.find_task_by_pid_ns = probe_find_task_by_pid_ns(); | |
1260 | - if (!caitsith_exports.find_task_by_pid_ns) | |
1261 | - goto out; | |
1262 | - caitsith_exports.d_absolute_path = probe_d_absolute_path(); | |
1263 | - if (!caitsith_exports.d_absolute_path) | |
1264 | - goto out; | |
1265 | - for (idx = 0; idx < CS_MAX_TASK_SECURITY_HASH; idx++) { | |
1266 | - INIT_LIST_HEAD(&cs_cred_security_list[idx]); | |
1267 | - INIT_LIST_HEAD(&cs_task_security_list[idx]); | |
1268 | - } | |
1269 | - cs_init_module(); | |
1270 | - swap_hook(&caitsith_hooks[0], &original_cred_free); | |
1271 | - swap_hook(&caitsith_hooks[1], &original_cred_prepare); | |
1272 | - swap_hook(&caitsith_hooks[2], &original_cred_alloc_blank); | |
1273 | - for (idx = 3; idx < ARRAY_SIZE(caitsith_hooks); idx++) | |
1274 | - add_hook(&caitsith_hooks[idx]); | |
1275 | - return 0; | |
1276 | -out: | |
1277 | - return -EINVAL; | |
1278 | -} | |
1279 | - | |
1280 | -module_init(cs_init); | |
1281 | -MODULE_LICENSE("GPL"); | |
1282 | - | |
1283 | -/** | |
1284 | - * cs_used_by_cred - Check whether the given domain is in use or not. | |
1285 | - * | |
1286 | - * @domain: Pointer to "struct cs_domain_info". | |
1287 | - * | |
1288 | - * Returns true if @domain is in use, false otherwise. | |
1289 | - * | |
1290 | - * Caller holds rcu_read_lock(). | |
1291 | - */ | |
1292 | -bool cs_used_by_cred(const struct cs_domain_info *domain) | |
1293 | -{ | |
1294 | - int idx; | |
1295 | - struct cs_security *ptr; | |
1296 | - for (idx = 0; idx < CS_MAX_TASK_SECURITY_HASH; idx++) { | |
1297 | - struct list_head *list = &cs_cred_security_list[idx]; | |
1298 | - list_for_each_entry_rcu(ptr, list, list) { | |
1299 | - struct cs_request_info *r = ptr->r; | |
1300 | - if (ptr->cs_domain_info == domain || | |
1301 | - (r && r->previous_domain == domain)) { | |
1302 | - return true; | |
1303 | - } | |
1304 | - } | |
1305 | - } | |
1306 | - return false; | |
1307 | -} | |
1308 | - | |
1309 | -/** | |
1310 | - * cs_add_task_security - Add "struct cs_security" to list. | |
1311 | - * | |
1312 | - * @ptr: Pointer to "struct cs_security". | |
1313 | - * @list: Pointer to "struct list_head". | |
1314 | - * | |
1315 | - * Returns nothing. | |
1316 | - */ | |
1317 | -static void cs_add_task_security(struct cs_security *ptr, | |
1318 | - struct list_head *list) | |
1319 | -{ | |
1320 | - unsigned long flags; | |
1321 | - spin_lock_irqsave(&cs_task_security_list_lock, flags); | |
1322 | - list_add_rcu(&ptr->list, list); | |
1323 | - spin_unlock_irqrestore(&cs_task_security_list_lock, flags); | |
1324 | -} | |
1325 | - | |
1326 | -/** | |
1327 | - * cs_find_task_security - Find "struct cs_security" for given task. | |
1328 | - * | |
1329 | - * @task: Pointer to "struct task_struct". | |
1330 | - * | |
1331 | - * Returns pointer to "struct cs_security" on success, &cs_oom_security on | |
1332 | - * out of memory, &cs_default_security otherwise. | |
1333 | - * | |
1334 | - * If @task is current thread and "struct cs_security" for current thread was | |
1335 | - * not found, I try to allocate it. But if allocation failed, current thread | |
1336 | - * will be killed by SIGKILL. Note that if current->pid == 1, sending SIGKILL | |
1337 | - * won't work. | |
1338 | - */ | |
1339 | -struct cs_security *cs_find_task_security(const struct task_struct *task) | |
1340 | -{ | |
1341 | - struct cs_security *ptr; | |
1342 | - struct list_head *list = &cs_task_security_list | |
1343 | - [hash_ptr((void *) task, CS_TASK_SECURITY_HASH_BITS)]; | |
1344 | - /* Make sure INIT_LIST_HEAD() in cs_mm_init() takes effect. */ | |
1345 | - while (!list->next); | |
1346 | - rcu_read_lock(); | |
1347 | - list_for_each_entry_rcu(ptr, list, list) { | |
1348 | - if (ptr->pid != task->pids[PIDTYPE_PID].pid) | |
1349 | - continue; | |
1350 | - rcu_read_unlock(); | |
1351 | - /* | |
1352 | - * Current thread needs to transit from old domain to new | |
1353 | - * domain before do_execve() succeeds in order to check | |
1354 | - * permission for interpreters and environment variables using | |
1355 | - * new domain's ACL rules. The domain transition has to be | |
1356 | - * visible from other CPU in order to allow interactive | |
1357 | - * enforcing mode. Also, the domain transition has to be | |
1358 | - * reverted if do_execve() failed. However, an LSM hook for | |
1359 | - * reverting domain transition is missing. | |
1360 | - * | |
1361 | - * security_prepare_creds() is called from prepare_creds() from | |
1362 | - * prepare_bprm_creds() from do_execve() before setting | |
1363 | - * current->in_execve flag, and current->in_execve flag is | |
1364 | - * cleared by the time next do_execve() request starts. | |
1365 | - * This means that we can emulate the missing LSM hook for | |
1366 | - * reverting domain transition, by calling this function from | |
1367 | - * security_prepare_creds(). | |
1368 | - * | |
1369 | - * If current->in_execve is not set but ptr->cs_flags has | |
1370 | - * CS_TASK_IS_IN_EXECVE set, it indicates that do_execve() | |
1371 | - * has failed and reverting domain transition is needed. | |
1372 | - */ | |
1373 | - if (task == current && | |
1374 | - (ptr->cs_flags & CS_TASK_IS_IN_EXECVE) && | |
1375 | - !current->in_execve) { | |
1376 | - cs_debug_trace("4"); | |
1377 | - cs_clear_execve(-1, ptr); | |
1378 | - } | |
1379 | - return ptr; | |
1380 | - } | |
1381 | - rcu_read_unlock(); | |
1382 | - if (task != current) { | |
1383 | - /* | |
1384 | - * If a thread does nothing after fork(), caller will reach | |
1385 | - * here because "struct cs_security" for that thread is not | |
1386 | - * yet allocated. But that thread is keeping a snapshot of | |
1387 | - * "struct cs_security" taken as of cs_task_create() | |
1388 | - * associated with that thread's "struct cred". | |
1389 | - * | |
1390 | - * Since that snapshot will be used as initial data when that | |
1391 | - * thread allocates "struct cs_security" for that thread, we | |
1392 | - * can return that snapshot rather than &cs_default_security. | |
1393 | - * | |
1394 | - * Since this function is called by only cs_select_one() and | |
1395 | - * cs_read_pid() (via cs_task_domain() and cs_task_flags()), | |
1396 | - * it is guaranteed that caller has called rcu_read_lock() | |
1397 | - * (via cs_tasklist_lock()) before finding this thread and | |
1398 | - * this thread is valid. Therefore, we can do __task_cred(task) | |
1399 | - * like get_robust_list() does. | |
1400 | - */ | |
1401 | - return cs_find_cred_security(__task_cred(task)); | |
1402 | - } | |
1403 | - /* Use GFP_ATOMIC because caller may have called rcu_read_lock(). */ | |
1404 | - ptr = kzalloc(sizeof(*ptr), GFP_ATOMIC); | |
1405 | - if (!ptr) { | |
1406 | - printk(KERN_WARNING "Unable to allocate memory for pid=%u\n", | |
1407 | - task->pid); | |
1408 | - send_sig(SIGKILL, current, 0); | |
1409 | - return &cs_oom_security; | |
1410 | - } | |
1411 | - *ptr = *cs_find_cred_security(task->cred); | |
1412 | - /* We can shortcut because task == current. */ | |
1413 | - ptr->pid = get_pid(((struct task_struct *) task)-> | |
1414 | - pids[PIDTYPE_PID].pid); | |
1415 | - ptr->cred = NULL; | |
1416 | - cs_add_task_security(ptr, list); | |
1417 | - return ptr; | |
1418 | -} | |
1419 | - | |
1420 | -/** | |
1421 | - * cs_copy_cred_security - Allocate memory for new credentials. | |
1422 | - * | |
1423 | - * @new: Pointer to "struct cred". | |
1424 | - * @old: Pointer to "struct cred". | |
1425 | - * @gfp: Memory allocation flags. | |
1426 | - * | |
1427 | - * Returns 0 on success, negative value otherwise. | |
1428 | - */ | |
1429 | -static int cs_copy_cred_security(const struct cred *new, | |
1430 | - const struct cred *old, gfp_t gfp) | |
1431 | -{ | |
1432 | - struct cs_security *old_security = cs_find_cred_security(old); | |
1433 | - struct cs_security *new_security = | |
1434 | - kzalloc(sizeof(*new_security), gfp); | |
1435 | - if (!new_security) | |
1436 | - return -ENOMEM; | |
1437 | - *new_security = *old_security; | |
1438 | - new_security->cred = new; | |
1439 | - cs_add_cred_security(new_security); | |
1440 | - return 0; | |
1441 | -} | |
1442 | - | |
1443 | -/** | |
1444 | - * cs_find_cred_security - Find "struct cs_security" for given credential. | |
1445 | - * | |
1446 | - * @cred: Pointer to "struct cred". | |
1447 | - * | |
1448 | - * Returns pointer to "struct cs_security" on success, &cs_default_security | |
1449 | - * otherwise. | |
1450 | - */ | |
1451 | -static struct cs_security *cs_find_cred_security(const struct cred *cred) | |
1452 | -{ | |
1453 | - struct cs_security *ptr; | |
1454 | - struct list_head *list = &cs_cred_security_list | |
1455 | - [hash_ptr((void *) cred, CS_TASK_SECURITY_HASH_BITS)]; | |
1456 | - rcu_read_lock(); | |
1457 | - list_for_each_entry_rcu(ptr, list, list) { | |
1458 | - if (ptr->cred != cred) | |
1459 | - continue; | |
1460 | - rcu_read_unlock(); | |
1461 | - return ptr; | |
1462 | - } | |
1463 | - rcu_read_unlock(); | |
1464 | - return &cs_default_security; | |
1465 | -} | |
1466 | - | |
1467 | -/** | |
1468 | - * cs_task_security_gc - Do garbage collection for "struct task_struct". | |
1469 | - * | |
1470 | - * Returns nothing. | |
1471 | - * | |
1472 | - * Since security_task_free() is missing, I can't release memory associated | |
1473 | - * with "struct task_struct" when a task dies. Therefore, I hold a reference on | |
1474 | - * "struct pid" and runs garbage collection when associated | |
1475 | - * "struct task_struct" has gone. | |
1476 | - */ | |
1477 | -static void cs_task_security_gc(void) | |
1478 | -{ | |
1479 | - static DEFINE_SPINLOCK(lock); | |
1480 | - static atomic_t gc_counter = ATOMIC_INIT(0); | |
1481 | - unsigned int idx; | |
1482 | - /* | |
1483 | - * If some process is doing execve(), try to garbage collection now. | |
1484 | - * We should kfree() memory associated with "struct cs_security"->r | |
1485 | - * as soon as execve() has completed in order to compensate for lack of | |
1486 | - * security_bprm_free() and security_task_free() hooks. | |
1487 | - * | |
1488 | - * Otherwise, reduce frequency for performance reason. | |
1489 | - */ | |
1490 | - if (!atomic_read(&cs_in_execve_tasks) && | |
1491 | - atomic_inc_return(&gc_counter) < 1024) | |
1492 | - return; | |
1493 | - if (!spin_trylock(&lock)) | |
1494 | - return; | |
1495 | - atomic_set(&gc_counter, 0); | |
1496 | - rcu_read_lock(); | |
1497 | - for (idx = 0; idx < CS_MAX_TASK_SECURITY_HASH; idx++) { | |
1498 | - struct cs_security *ptr; | |
1499 | - struct list_head *list = &cs_task_security_list[idx]; | |
1500 | - list_for_each_entry_rcu(ptr, list, list) { | |
1501 | - if (pid_task(ptr->pid, PIDTYPE_PID)) | |
1502 | - continue; | |
1503 | - cs_del_security(ptr); | |
1504 | - } | |
1505 | - } | |
1506 | - rcu_read_unlock(); | |
1507 | - spin_unlock(&lock); | |
1508 | -} |
@@ -437,7 +437,7 @@ | ||
437 | 437 | static int cs_inode_setattr(struct dentry *dentry, struct iattr *attr) |
438 | 438 | { |
439 | 439 | int rc = 0; |
440 | - struct path path = { NULL, dentry }; | |
440 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
441 | 441 | if (attr->ia_valid & ATTR_UID) |
442 | 442 | rc = cs_chown_permission(&path, attr->ia_uid, -1); |
443 | 443 | if (!rc && (attr->ia_valid & ATTR_GID)) |
@@ -462,7 +462,7 @@ | ||
462 | 462 | */ |
463 | 463 | static int cs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
464 | 464 | { |
465 | - struct path path = { mnt, dentry }; | |
465 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
466 | 466 | int rc = cs_getattr_permission(&path); |
467 | 467 | if (rc) |
468 | 468 | return rc; |
@@ -483,7 +483,7 @@ | ||
483 | 483 | static int cs_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, |
484 | 484 | dev_t dev) |
485 | 485 | { |
486 | - struct path path = { NULL, dentry }; | |
486 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
487 | 487 | int rc = cs_mknod_permission(&path, mode, dev); |
488 | 488 | if (rc) |
489 | 489 | return rc; |
@@ -502,7 +502,7 @@ | ||
502 | 502 | */ |
503 | 503 | static int cs_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
504 | 504 | { |
505 | - struct path path = { NULL, dentry }; | |
505 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
506 | 506 | int rc = cs_mkdir_permission(&path, mode); |
507 | 507 | if (rc) |
508 | 508 | return rc; |
@@ -520,7 +520,7 @@ | ||
520 | 520 | */ |
521 | 521 | static int cs_inode_rmdir(struct inode *dir, struct dentry *dentry) |
522 | 522 | { |
523 | - struct path path = { NULL, dentry }; | |
523 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
524 | 524 | int rc = cs_rmdir_permission(&path); |
525 | 525 | if (rc) |
526 | 526 | return rc; |
@@ -538,7 +538,7 @@ | ||
538 | 538 | */ |
539 | 539 | static int cs_inode_unlink(struct inode *dir, struct dentry *dentry) |
540 | 540 | { |
541 | - struct path path = { NULL, dentry }; | |
541 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
542 | 542 | int rc = cs_unlink_permission(&path); |
543 | 543 | if (rc) |
544 | 544 | return rc; |
@@ -558,7 +558,7 @@ | ||
558 | 558 | static int cs_inode_symlink(struct inode *dir, struct dentry *dentry, |
559 | 559 | const char *old_name) |
560 | 560 | { |
561 | - struct path path = { NULL, dentry }; | |
561 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
562 | 562 | int rc = cs_symlink_permission(&path, old_name); |
563 | 563 | if (rc) |
564 | 564 | return rc; |
@@ -622,7 +622,7 @@ | ||
622 | 622 | static int cs_inode_create(struct inode *dir, struct dentry *dentry, |
623 | 623 | int mode) |
624 | 624 | { |
625 | - struct path path = { NULL, dentry }; | |
625 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
626 | 626 | int rc = cs_mknod_permission(&path, mode, 0); |
627 | 627 | if (rc) |
628 | 628 | return rc; |
@@ -1055,7 +1055,7 @@ | ||
1055 | 1055 | */ |
1056 | 1056 | static int cs_sb_umount(struct vfsmount *mnt, int flags) |
1057 | 1057 | { |
1058 | - struct path path = { mnt, mnt->mnt_root }; | |
1058 | + struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; | |
1059 | 1059 | int rc = cs_umount_permission(&path, flags); |
1060 | 1060 | if (rc) |
1061 | 1061 | return rc; |
@@ -625,7 +625,7 @@ | ||
625 | 625 | static int cs_path_chmod(struct dentry *dentry, struct vfsmount *vfsmnt, |
626 | 626 | mode_t mode) |
627 | 627 | { |
628 | - struct path path = { vfsmnt, dentry }; | |
628 | + struct path path = { .mnt = vfsmnt, .dentry = dentry }; | |
629 | 629 | int rc = cs_chmod_permission(&path, mode); |
630 | 630 | if (rc) |
631 | 631 | return rc; |
@@ -708,7 +708,7 @@ | ||
708 | 708 | { |
709 | 709 | int rc = 0; |
710 | 710 | #if !defined(CONFIG_SECURITY_PATH) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) |
711 | - struct path path = { NULL, dentry }; | |
711 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
712 | 712 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) |
713 | 713 | if (attr->ia_valid & ATTR_UID) |
714 | 714 | rc = cs_chown_permission(&path, attr->ia_uid, INVALID_GID); |
@@ -763,7 +763,7 @@ | ||
763 | 763 | */ |
764 | 764 | static int cs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
765 | 765 | { |
766 | - struct path path = { mnt, dentry }; | |
766 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
767 | 767 | int rc = cs_getattr_permission(&path); |
768 | 768 | if (rc) |
769 | 769 | return rc; |
@@ -790,7 +790,7 @@ | ||
790 | 790 | static int cs_path_mknod(struct path *dir, struct dentry *dentry, |
791 | 791 | umode_t mode, unsigned int dev) |
792 | 792 | { |
793 | - struct path path = { dir->mnt, dentry }; | |
793 | + struct path path = { .mnt = dir->mnt, .dentry = dentry }; | |
794 | 794 | int rc = cs_mknod_permission(&path, mode, dev); |
795 | 795 | if (rc) |
796 | 796 | return rc; |
@@ -810,7 +810,7 @@ | ||
810 | 810 | static int cs_path_mkdir(struct path *dir, struct dentry *dentry, |
811 | 811 | umode_t mode) |
812 | 812 | { |
813 | - struct path path = { dir->mnt, dentry }; | |
813 | + struct path path = { .mnt = dir->mnt, .dentry = dentry }; | |
814 | 814 | int rc = cs_mkdir_permission(&path, mode); |
815 | 815 | if (rc) |
816 | 816 | return rc; |
@@ -833,7 +833,7 @@ | ||
833 | 833 | static int cs_path_mknod(struct path *dir, struct dentry *dentry, int mode, |
834 | 834 | unsigned int dev) |
835 | 835 | { |
836 | - struct path path = { dir->mnt, dentry }; | |
836 | + struct path path = { .mnt = dir->mnt, .dentry = dentry }; | |
837 | 837 | int rc = cs_mknod_permission(&path, mode, dev); |
838 | 838 | if (rc) |
839 | 839 | return rc; |
@@ -852,7 +852,7 @@ | ||
852 | 852 | */ |
853 | 853 | static int cs_path_mkdir(struct path *dir, struct dentry *dentry, int mode) |
854 | 854 | { |
855 | - struct path path = { dir->mnt, dentry }; | |
855 | + struct path path = { .mnt = dir->mnt, .dentry = dentry }; | |
856 | 856 | int rc = cs_mkdir_permission(&path, mode); |
857 | 857 | if (rc) |
858 | 858 | return rc; |
@@ -872,7 +872,7 @@ | ||
872 | 872 | */ |
873 | 873 | static int cs_path_rmdir(struct path *dir, struct dentry *dentry) |
874 | 874 | { |
875 | - struct path path = { dir->mnt, dentry }; | |
875 | + struct path path = { .mnt = dir->mnt, .dentry = dentry }; | |
876 | 876 | int rc = cs_rmdir_permission(&path); |
877 | 877 | if (rc) |
878 | 878 | return rc; |
@@ -890,7 +890,7 @@ | ||
890 | 890 | */ |
891 | 891 | static int cs_path_unlink(struct path *dir, struct dentry *dentry) |
892 | 892 | { |
893 | - struct path path = { dir->mnt, dentry }; | |
893 | + struct path path = { .mnt = dir->mnt, .dentry = dentry }; | |
894 | 894 | int rc = cs_unlink_permission(&path); |
895 | 895 | if (rc) |
896 | 896 | return rc; |
@@ -910,7 +910,7 @@ | ||
910 | 910 | static int cs_path_symlink(struct path *dir, struct dentry *dentry, |
911 | 911 | const char *old_name) |
912 | 912 | { |
913 | - struct path path = { dir->mnt, dentry }; | |
913 | + struct path path = { .mnt = dir->mnt, .dentry = dentry }; | |
914 | 914 | int rc = cs_symlink_permission(&path, old_name); |
915 | 915 | if (rc) |
916 | 916 | return rc; |
@@ -980,7 +980,7 @@ | ||
980 | 980 | static int cs_inode_mknod(struct inode *dir, struct dentry *dentry, |
981 | 981 | umode_t mode, dev_t dev) |
982 | 982 | { |
983 | - struct path path = { NULL, dentry }; | |
983 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
984 | 984 | int rc = cs_mknod_permission(&path, mode, dev); |
985 | 985 | if (rc) |
986 | 986 | return rc; |
@@ -1000,7 +1000,7 @@ | ||
1000 | 1000 | static int cs_inode_mkdir(struct inode *dir, struct dentry *dentry, |
1001 | 1001 | umode_t mode) |
1002 | 1002 | { |
1003 | - struct path path = { NULL, dentry }; | |
1003 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
1004 | 1004 | int rc = cs_mkdir_permission(&path, mode); |
1005 | 1005 | if (rc) |
1006 | 1006 | return rc; |
@@ -1023,7 +1023,7 @@ | ||
1023 | 1023 | static int cs_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, |
1024 | 1024 | dev_t dev) |
1025 | 1025 | { |
1026 | - struct path path = { NULL, dentry }; | |
1026 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
1027 | 1027 | int rc = cs_mknod_permission(&path, mode, dev); |
1028 | 1028 | if (rc) |
1029 | 1029 | return rc; |
@@ -1042,7 +1042,7 @@ | ||
1042 | 1042 | */ |
1043 | 1043 | static int cs_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
1044 | 1044 | { |
1045 | - struct path path = { NULL, dentry }; | |
1045 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
1046 | 1046 | int rc = cs_mkdir_permission(&path, mode); |
1047 | 1047 | if (rc) |
1048 | 1048 | return rc; |
@@ -1062,7 +1062,7 @@ | ||
1062 | 1062 | */ |
1063 | 1063 | static int cs_inode_rmdir(struct inode *dir, struct dentry *dentry) |
1064 | 1064 | { |
1065 | - struct path path = { NULL, dentry }; | |
1065 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
1066 | 1066 | int rc = cs_rmdir_permission(&path); |
1067 | 1067 | if (rc) |
1068 | 1068 | return rc; |
@@ -1080,7 +1080,7 @@ | ||
1080 | 1080 | */ |
1081 | 1081 | static int cs_inode_unlink(struct inode *dir, struct dentry *dentry) |
1082 | 1082 | { |
1083 | - struct path path = { NULL, dentry }; | |
1083 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
1084 | 1084 | int rc = cs_unlink_permission(&path); |
1085 | 1085 | if (rc) |
1086 | 1086 | return rc; |
@@ -1100,7 +1100,7 @@ | ||
1100 | 1100 | static int cs_inode_symlink(struct inode *dir, struct dentry *dentry, |
1101 | 1101 | const char *old_name) |
1102 | 1102 | { |
1103 | - struct path path = { NULL, dentry }; | |
1103 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
1104 | 1104 | int rc = cs_symlink_permission(&path, old_name); |
1105 | 1105 | if (rc) |
1106 | 1106 | return rc; |
@@ -1166,7 +1166,7 @@ | ||
1166 | 1166 | static int cs_inode_create(struct inode *dir, struct dentry *dentry, |
1167 | 1167 | umode_t mode) |
1168 | 1168 | { |
1169 | - struct path path = { NULL, dentry }; | |
1169 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
1170 | 1170 | int rc = cs_mknod_permission(&path, mode, 0); |
1171 | 1171 | if (rc) |
1172 | 1172 | return rc; |
@@ -1188,7 +1188,7 @@ | ||
1188 | 1188 | static int cs_inode_create(struct inode *dir, struct dentry *dentry, |
1189 | 1189 | int mode) |
1190 | 1190 | { |
1191 | - struct path path = { NULL, dentry }; | |
1191 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
1192 | 1192 | int rc = cs_mknod_permission(&path, mode, 0); |
1193 | 1193 | if (rc) |
1194 | 1194 | return rc; |
@@ -1670,7 +1670,7 @@ | ||
1670 | 1670 | */ |
1671 | 1671 | static int cs_sb_umount(struct vfsmount *mnt, int flags) |
1672 | 1672 | { |
1673 | - struct path path = { mnt, mnt->mnt_root }; | |
1673 | + struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; | |
1674 | 1674 | int rc = cs_umount_permission(&path, flags); |
1675 | 1675 | if (rc) |
1676 | 1676 | return rc; |
@@ -8,7 +8,7 @@ | ||
8 | 8 | |
9 | 9 | #include <linux/version.h> |
10 | 10 | #include <linux/security.h> |
11 | -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) && !defined(SECURITY_NAME_MAX) | |
11 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) | |
12 | 12 | #include "lsm-4.2.c" |
13 | 13 | #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) |
14 | 14 | #include "lsm-2.6.29.c" |
@@ -483,7 +483,7 @@ | ||
483 | 483 | static int cs_inode_setattr(struct dentry *dentry, struct iattr *attr) |
484 | 484 | { |
485 | 485 | int rc = 0; |
486 | - struct path path = { NULL, dentry }; | |
486 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
487 | 487 | if (attr->ia_valid & ATTR_UID) |
488 | 488 | rc = cs_chown_permission(&path, attr->ia_uid, INVALID_GID); |
489 | 489 | if (!rc && (attr->ia_valid & ATTR_GID)) |
@@ -524,7 +524,7 @@ | ||
524 | 524 | static int cs_path_mknod(struct path *dir, struct dentry *dentry, |
525 | 525 | umode_t mode, unsigned int dev) |
526 | 526 | { |
527 | - struct path path = { dir->mnt, dentry }; | |
527 | + struct path path = { .mnt = dir->mnt, .dentry = dentry }; | |
528 | 528 | return cs_mknod_permission(&path, mode, dev); |
529 | 529 | } |
530 | 530 |
@@ -540,7 +540,7 @@ | ||
540 | 540 | static int cs_path_mkdir(struct path *dir, struct dentry *dentry, |
541 | 541 | umode_t mode) |
542 | 542 | { |
543 | - struct path path = { dir->mnt, dentry }; | |
543 | + struct path path = { .mnt = dir->mnt, .dentry = dentry }; | |
544 | 544 | return cs_mkdir_permission(&path, mode); |
545 | 545 | } |
546 | 546 |
@@ -554,7 +554,7 @@ | ||
554 | 554 | */ |
555 | 555 | static int cs_path_rmdir(struct path *dir, struct dentry *dentry) |
556 | 556 | { |
557 | - struct path path = { dir->mnt, dentry }; | |
557 | + struct path path = { .mnt = dir->mnt, .dentry = dentry }; | |
558 | 558 | return cs_rmdir_permission(&path); |
559 | 559 | } |
560 | 560 |
@@ -568,7 +568,7 @@ | ||
568 | 568 | */ |
569 | 569 | static int cs_path_unlink(struct path *dir, struct dentry *dentry) |
570 | 570 | { |
571 | - struct path path = { dir->mnt, dentry }; | |
571 | + struct path path = { .mnt = dir->mnt, .dentry = dentry }; | |
572 | 572 | return cs_unlink_permission(&path); |
573 | 573 | } |
574 | 574 |
@@ -584,7 +584,7 @@ | ||
584 | 584 | static int cs_path_symlink(struct path *dir, struct dentry *dentry, |
585 | 585 | const char *old_name) |
586 | 586 | { |
587 | - struct path path = { dir->mnt, dentry }; | |
587 | + struct path path = { .mnt = dir->mnt, .dentry = dentry }; | |
588 | 588 | return cs_symlink_permission(&path, old_name); |
589 | 589 | } |
590 | 590 |
@@ -638,7 +638,7 @@ | ||
638 | 638 | static int cs_inode_mknod(struct inode *dir, struct dentry *dentry, |
639 | 639 | umode_t mode, dev_t dev) |
640 | 640 | { |
641 | - struct path path = { NULL, dentry }; | |
641 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
642 | 642 | return cs_mknod_permission(&path, mode, dev); |
643 | 643 | } |
644 | 644 |
@@ -654,7 +654,7 @@ | ||
654 | 654 | static int cs_inode_mkdir(struct inode *dir, struct dentry *dentry, |
655 | 655 | umode_t mode) |
656 | 656 | { |
657 | - struct path path = { NULL, dentry }; | |
657 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
658 | 658 | return cs_mkdir_permission(&path, mode); |
659 | 659 | } |
660 | 660 |
@@ -668,7 +668,7 @@ | ||
668 | 668 | */ |
669 | 669 | static int cs_inode_rmdir(struct inode *dir, struct dentry *dentry) |
670 | 670 | { |
671 | - struct path path = { NULL, dentry }; | |
671 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
672 | 672 | return cs_rmdir_permission(&path); |
673 | 673 | } |
674 | 674 |
@@ -682,7 +682,7 @@ | ||
682 | 682 | */ |
683 | 683 | static int cs_inode_unlink(struct inode *dir, struct dentry *dentry) |
684 | 684 | { |
685 | - struct path path = { NULL, dentry }; | |
685 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
686 | 686 | return cs_unlink_permission(&path); |
687 | 687 | } |
688 | 688 |
@@ -698,7 +698,7 @@ | ||
698 | 698 | static int cs_inode_symlink(struct inode *dir, struct dentry *dentry, |
699 | 699 | const char *old_name) |
700 | 700 | { |
701 | - struct path path = { NULL, dentry }; | |
701 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
702 | 702 | return cs_symlink_permission(&path, old_name); |
703 | 703 | } |
704 | 704 |
@@ -749,7 +749,7 @@ | ||
749 | 749 | static int cs_inode_create(struct inode *dir, struct dentry *dentry, |
750 | 750 | umode_t mode) |
751 | 751 | { |
752 | - struct path path = { NULL, dentry }; | |
752 | + struct path path = { .mnt = NULL, .dentry = dentry }; | |
753 | 753 | return cs_mknod_permission(&path, mode, 0); |
754 | 754 | } |
755 | 755 |
@@ -1123,7 +1123,7 @@ | ||
1123 | 1123 | */ |
1124 | 1124 | static int cs_sb_umount(struct vfsmount *mnt, int flags) |
1125 | 1125 | { |
1126 | - struct path path = { mnt, mnt->mnt_root }; | |
1126 | + struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; | |
1127 | 1127 | return cs_umount_permission(&path, flags); |
1128 | 1128 | } |
1129 | 1129 |
@@ -100,7 +100,7 @@ | ||
100 | 100 | mntput(mnt); |
101 | 101 | else { |
102 | 102 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) |
103 | - struct path path = { mnt, dentry }; | |
103 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
104 | 104 | file = dentry_open(&path, O_RDONLY, current_cred()); |
105 | 105 | #else |
106 | 106 | file = dentry_open(dentry, mnt, O_RDONLY |
@@ -439,7 +439,7 @@ | ||
439 | 439 | struct iattr *attr) |
440 | 440 | { |
441 | 441 | int rc = 0; |
442 | - struct path path = { mnt, dentry }; | |
442 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
443 | 443 | if (attr->ia_valid & ATTR_UID) |
444 | 444 | rc = cs_chown_permission(&path, attr->ia_uid, -1); |
445 | 445 | if (!rc && (attr->ia_valid & ATTR_GID)) |
@@ -464,7 +464,7 @@ | ||
464 | 464 | */ |
465 | 465 | static int cs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
466 | 466 | { |
467 | - struct path path = { mnt, dentry }; | |
467 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
468 | 468 | int rc = cs_getattr_permission(&path); |
469 | 469 | if (rc) |
470 | 470 | return rc; |
@@ -486,7 +486,7 @@ | ||
486 | 486 | static int cs_inode_mknod(struct inode *dir, struct dentry *dentry, |
487 | 487 | struct vfsmount *mnt, int mode, dev_t dev) |
488 | 488 | { |
489 | - struct path path = { mnt, dentry }; | |
489 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
490 | 490 | int rc = cs_mknod_permission(&path, mode, dev); |
491 | 491 | if (rc) |
492 | 492 | return rc; |
@@ -507,7 +507,7 @@ | ||
507 | 507 | static int cs_inode_mkdir(struct inode *dir, struct dentry *dentry, |
508 | 508 | struct vfsmount *mnt, int mode) |
509 | 509 | { |
510 | - struct path path = { mnt, dentry }; | |
510 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
511 | 511 | int rc = cs_mkdir_permission(&path, mode); |
512 | 512 | if (rc) |
513 | 513 | return rc; |
@@ -527,7 +527,7 @@ | ||
527 | 527 | static int cs_inode_rmdir(struct inode *dir, struct dentry *dentry, |
528 | 528 | struct vfsmount *mnt) |
529 | 529 | { |
530 | - struct path path = { mnt, dentry }; | |
530 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
531 | 531 | int rc = cs_rmdir_permission(&path); |
532 | 532 | if (rc) |
533 | 533 | return rc; |
@@ -547,7 +547,7 @@ | ||
547 | 547 | static int cs_inode_unlink(struct inode *dir, struct dentry *dentry, |
548 | 548 | struct vfsmount *mnt) |
549 | 549 | { |
550 | - struct path path = { mnt, dentry }; | |
550 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
551 | 551 | int rc = cs_unlink_permission(&path); |
552 | 552 | if (rc) |
553 | 553 | return rc; |
@@ -568,7 +568,7 @@ | ||
568 | 568 | static int cs_inode_symlink(struct inode *dir, struct dentry *dentry, |
569 | 569 | struct vfsmount *mnt, const char *old_name) |
570 | 570 | { |
571 | - struct path path = { mnt, dentry }; | |
571 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
572 | 572 | int rc = cs_symlink_permission(&path, old_name); |
573 | 573 | if (rc) |
574 | 574 | return rc; |
@@ -642,7 +642,7 @@ | ||
642 | 642 | static int cs_inode_create(struct inode *dir, struct dentry *dentry, |
643 | 643 | struct vfsmount *mnt, int mode) |
644 | 644 | { |
645 | - struct path path = { mnt, dentry }; | |
645 | + struct path path = { .mnt = mnt, .dentry = dentry }; | |
646 | 646 | int rc = cs_mknod_permission(&path, mode, 0); |
647 | 647 | if (rc) |
648 | 648 | return rc; |
@@ -1075,7 +1075,7 @@ | ||
1075 | 1075 | */ |
1076 | 1076 | static int cs_sb_umount(struct vfsmount *mnt, int flags) |
1077 | 1077 | { |
1078 | - struct path path = { mnt, mnt->mnt_root }; | |
1078 | + struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; | |
1079 | 1079 | int rc = cs_umount_permission(&path, flags); |
1080 | 1080 | if (rc) |
1081 | 1081 | return rc; |