vfs_acl.c (191266) | vfs_acl.c (192586) |
---|---|
1/*- 2 * Copyright (c) 1999-2006 Robert N. M. Watson 3 * All rights reserved. 4 * 5 * This software was developed by Robert Watson for the TrustedBSD Project. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 19 unchanged lines hidden (view full) --- 28/* 29 * Developed by the TrustedBSD Project. 30 * 31 * ACL system calls and other functions common across different ACL types. 32 * Type-specific routines go into subr_acl_<type>.c. 33 */ 34 35#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1999-2006 Robert N. M. Watson 3 * All rights reserved. 4 * 5 * This software was developed by Robert Watson for the TrustedBSD Project. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 19 unchanged lines hidden (view full) --- 28/* 29 * Developed by the TrustedBSD Project. 30 * 31 * ACL system calls and other functions common across different ACL types. 32 * Type-specific routines go into subr_acl_<type>.c. 33 */ 34 35#include <sys/cdefs.h> |
36__FBSDID("$FreeBSD: head/sys/kern/vfs_acl.c 191266 2009-04-19 09:56:30Z trasz $"); | 36__FBSDID("$FreeBSD: head/sys/kern/vfs_acl.c 192586 2009-05-22 15:56:43Z trasz $"); |
37 38#include "opt_mac.h" 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/sysproto.h> 43#include <sys/fcntl.h> 44#include <sys/kernel.h> --- 6 unchanged lines hidden (view full) --- 51#include <sys/file.h> 52#include <sys/filedesc.h> 53#include <sys/proc.h> 54#include <sys/sysent.h> 55#include <sys/acl.h> 56 57#include <security/mac/mac_framework.h> 58 | 37 38#include "opt_mac.h" 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/sysproto.h> 43#include <sys/fcntl.h> 44#include <sys/kernel.h> --- 6 unchanged lines hidden (view full) --- 51#include <sys/file.h> 52#include <sys/filedesc.h> 53#include <sys/proc.h> 54#include <sys/sysent.h> 55#include <sys/acl.h> 56 57#include <security/mac/mac_framework.h> 58 |
59static MALLOC_DEFINE(M_ACL, "acl", "Access Control Lists"); | 59CTASSERT(ACL_MAX_ENTRIES >= OLDACL_MAX_ENTRIES); |
60 | 60 |
61MALLOC_DEFINE(M_ACL, "acl", "Access Control Lists"); 62 |
|
61static int vacl_set_acl(struct thread *td, struct vnode *vp, 62 acl_type_t type, struct acl *aclp); 63static int vacl_get_acl(struct thread *td, struct vnode *vp, 64 acl_type_t type, struct acl *aclp); 65static int vacl_aclcheck(struct thread *td, struct vnode *vp, 66 acl_type_t type, struct acl *aclp); 67 | 63static int vacl_set_acl(struct thread *td, struct vnode *vp, 64 acl_type_t type, struct acl *aclp); 65static int vacl_get_acl(struct thread *td, struct vnode *vp, 66 acl_type_t type, struct acl *aclp); 67static int vacl_aclcheck(struct thread *td, struct vnode *vp, 68 acl_type_t type, struct acl *aclp); 69 |
70int 71acl_copy_oldacl_into_acl(const struct oldacl *source, struct acl *dest) 72{ 73 int i; 74 75 if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES) 76 return (EINVAL); 77 78 bzero(dest, sizeof(*dest)); 79 80 dest->acl_cnt = source->acl_cnt; 81 dest->acl_maxcnt = ACL_MAX_ENTRIES; 82 83 for (i = 0; i < dest->acl_cnt; i++) { 84 dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; 85 dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; 86 dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; 87 } 88 89 return (0); 90} 91 92int 93acl_copy_acl_into_oldacl(const struct acl *source, struct oldacl *dest) 94{ 95 int i; 96 97 if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES) 98 return (EINVAL); 99 100 bzero(dest, sizeof(*dest)); 101 102 dest->acl_cnt = source->acl_cnt; 103 104 for (i = 0; i < dest->acl_cnt; i++) { 105 dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag; 106 dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id; 107 dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm; 108 } 109 110 return (0); 111} 112 |
|
68/* | 113/* |
114 * At one time, "struct ACL" was extended in order to add support for NFSv4 115 * ACLs. Instead of creating compatibility versions of all the ACL-related 116 * syscalls, they were left intact. It's possible to find out what the code 117 * calling these syscalls (libc) expects basing on "type" argument - if it's 118 * either ACL_TYPE_ACCESS_OLD or ACL_TYPE_DEFAULT_OLD (which previously were 119 * known as ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT), then it's the "struct 120 * oldacl". If it's something else, then it's the new "struct acl". In the 121 * latter case, the routines below just copyin/copyout the contents. In the 122 * former case, they copyin the "struct oldacl" and convert it to the new 123 * format. 124 */ 125static int 126acl_copyin(void *user_acl, struct acl *kernel_acl, acl_type_t type) 127{ 128 int error; 129 struct oldacl old; 130 131 switch (type) { 132 case ACL_TYPE_ACCESS_OLD: 133 case ACL_TYPE_DEFAULT_OLD: 134 error = copyin(user_acl, &old, sizeof(old)); 135 if (error != 0) 136 break; 137 acl_copy_oldacl_into_acl(&old, kernel_acl); 138 break; 139 140 default: 141 error = copyin(user_acl, kernel_acl, sizeof(*kernel_acl)); 142 if (kernel_acl->acl_maxcnt != ACL_MAX_ENTRIES) 143 return (EINVAL); 144 } 145 146 return (error); 147} 148 149static int 150acl_copyout(struct acl *kernel_acl, void *user_acl, acl_type_t type) 151{ 152 int error; 153 struct oldacl old; 154 155 switch (type) { 156 case ACL_TYPE_ACCESS_OLD: 157 case ACL_TYPE_DEFAULT_OLD: 158 error = acl_copy_acl_into_oldacl(kernel_acl, &old); 159 if (error != 0) 160 break; 161 162 error = copyout(&old, user_acl, sizeof(old)); 163 break; 164 165 default: 166 if (fuword((char *)user_acl + 167 offsetof(struct acl, acl_maxcnt)) != ACL_MAX_ENTRIES) 168 return (EINVAL); 169 170 error = copyout(kernel_acl, user_acl, sizeof(*kernel_acl)); 171 } 172 173 return (error); 174} 175 176/* 177 * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new" 178 * counterpart. It's required for old (pre-NFS4 ACLs) libc to work 179 * with new kernel. Fixing 'type' for old binaries with new libc 180 * is being done in lib/libc/posix1e/acl_support.c:_acl_type_unold(). 181 */ 182static int 183acl_type_unold(int type) 184{ 185 switch (type) { 186 case ACL_TYPE_ACCESS_OLD: 187 return (ACL_TYPE_ACCESS); 188 189 case ACL_TYPE_DEFAULT_OLD: 190 return (ACL_TYPE_DEFAULT); 191 192 default: 193 return (type); 194 } 195} 196 197/* |
|
69 * These calls wrap the real vnode operations, and are called by the syscall 70 * code once the syscall has converted the path or file descriptor to a vnode 71 * (unlocked). The aclp pointer is assumed still to point to userland, so 72 * this should not be consumed within the kernel except by syscall code. 73 * Other code should directly invoke VOP_{SET,GET}ACL. 74 */ 75 76/* 77 * Given a vnode, set its ACL. 78 */ 79static int 80vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type, 81 struct acl *aclp) 82{ 83 struct acl *inkernelacl; 84 struct mount *mp; 85 int error; 86 87 inkernelacl = acl_alloc(M_WAITOK); | 198 * These calls wrap the real vnode operations, and are called by the syscall 199 * code once the syscall has converted the path or file descriptor to a vnode 200 * (unlocked). The aclp pointer is assumed still to point to userland, so 201 * this should not be consumed within the kernel except by syscall code. 202 * Other code should directly invoke VOP_{SET,GET}ACL. 203 */ 204 205/* 206 * Given a vnode, set its ACL. 207 */ 208static int 209vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type, 210 struct acl *aclp) 211{ 212 struct acl *inkernelacl; 213 struct mount *mp; 214 int error; 215 216 inkernelacl = acl_alloc(M_WAITOK); |
88 error = copyin(aclp, inkernelacl, sizeof(struct acl)); | 217 error = acl_copyin(aclp, inkernelacl, type); |
89 if (error) 90 goto out; 91 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 92 if (error != 0) 93 goto out; 94 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 95#ifdef MAC 96 error = mac_vnode_check_setacl(td->td_ucred, vp, type, inkernelacl); 97 if (error != 0) 98 goto out_unlock; 99#endif | 218 if (error) 219 goto out; 220 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 221 if (error != 0) 222 goto out; 223 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 224#ifdef MAC 225 error = mac_vnode_check_setacl(td->td_ucred, vp, type, inkernelacl); 226 if (error != 0) 227 goto out_unlock; 228#endif |
100 error = VOP_SETACL(vp, type, inkernelacl, td->td_ucred, td); | 229 error = VOP_SETACL(vp, acl_type_unold(type), inkernelacl, 230 td->td_ucred, td); |
101#ifdef MAC 102out_unlock: 103#endif 104 VOP_UNLOCK(vp, 0); 105 vn_finished_write(mp); 106out: 107 acl_free(inkernelacl); 108 return(error); --- 11 unchanged lines hidden (view full) --- 120 121 inkernelacl = acl_alloc(M_WAITOK); 122 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 123#ifdef MAC 124 error = mac_vnode_check_getacl(td->td_ucred, vp, type); 125 if (error != 0) 126 goto out; 127#endif | 231#ifdef MAC 232out_unlock: 233#endif 234 VOP_UNLOCK(vp, 0); 235 vn_finished_write(mp); 236out: 237 acl_free(inkernelacl); 238 return(error); --- 11 unchanged lines hidden (view full) --- 250 251 inkernelacl = acl_alloc(M_WAITOK); 252 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 253#ifdef MAC 254 error = mac_vnode_check_getacl(td->td_ucred, vp, type); 255 if (error != 0) 256 goto out; 257#endif |
128 error = VOP_GETACL(vp, type, inkernelacl, td->td_ucred, td); | 258 error = VOP_GETACL(vp, acl_type_unold(type), inkernelacl, 259 td->td_ucred, td); 260 |
129#ifdef MAC 130out: 131#endif 132 VOP_UNLOCK(vp, 0); 133 if (error == 0) | 261#ifdef MAC 262out: 263#endif 264 VOP_UNLOCK(vp, 0); 265 if (error == 0) |
134 error = copyout(inkernelacl, aclp, sizeof(struct acl)); | 266 error = acl_copyout(inkernelacl, aclp, type); |
135 acl_free(inkernelacl); 136 return (error); 137} 138 139/* 140 * Given a vnode, delete its ACL. 141 */ 142static int --- 6 unchanged lines hidden (view full) --- 149 if (error) 150 return (error); 151 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 152#ifdef MAC 153 error = mac_vnode_check_deleteacl(td->td_ucred, vp, type); 154 if (error) 155 goto out; 156#endif | 267 acl_free(inkernelacl); 268 return (error); 269} 270 271/* 272 * Given a vnode, delete its ACL. 273 */ 274static int --- 6 unchanged lines hidden (view full) --- 281 if (error) 282 return (error); 283 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 284#ifdef MAC 285 error = mac_vnode_check_deleteacl(td->td_ucred, vp, type); 286 if (error) 287 goto out; 288#endif |
157 error = VOP_SETACL(vp, type, 0, td->td_ucred, td); | 289 error = VOP_SETACL(vp, acl_type_unold(type), 0, td->td_ucred, td); |
158#ifdef MAC 159out: 160#endif 161 VOP_UNLOCK(vp, 0); 162 vn_finished_write(mp); 163 return (error); 164} 165 166/* 167 * Given a vnode, check whether an ACL is appropriate for it 168 */ 169static int 170vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type, 171 struct acl *aclp) 172{ 173 struct acl *inkernelacl; 174 int error; 175 176 inkernelacl = acl_alloc(M_WAITOK); | 290#ifdef MAC 291out: 292#endif 293 VOP_UNLOCK(vp, 0); 294 vn_finished_write(mp); 295 return (error); 296} 297 298/* 299 * Given a vnode, check whether an ACL is appropriate for it 300 */ 301static int 302vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type, 303 struct acl *aclp) 304{ 305 struct acl *inkernelacl; 306 int error; 307 308 inkernelacl = acl_alloc(M_WAITOK); |
177 error = copyin(aclp, inkernelacl, sizeof(struct acl)); | 309 error = acl_copyin(aclp, inkernelacl, type); |
178 if (error) 179 goto out; 180 error = VOP_ACLCHECK(vp, type, inkernelacl, td->td_ucred, td); 181out: 182 acl_free(inkernelacl); 183 return (error); 184} 185 --- 239 unchanged lines hidden (view full) --- 425} 426 427struct acl * 428acl_alloc(int flags) 429{ 430 struct acl *aclp; 431 432 aclp = malloc(sizeof(*aclp), M_ACL, flags); | 310 if (error) 311 goto out; 312 error = VOP_ACLCHECK(vp, type, inkernelacl, td->td_ucred, td); 313out: 314 acl_free(inkernelacl); 315 return (error); 316} 317 --- 239 unchanged lines hidden (view full) --- 557} 558 559struct acl * 560acl_alloc(int flags) 561{ 562 struct acl *aclp; 563 564 aclp = malloc(sizeof(*aclp), M_ACL, flags); |
565 aclp->acl_maxcnt = ACL_MAX_ENTRIES; |
|
433 434 return (aclp); 435} 436 437void 438acl_free(struct acl *aclp) 439{ 440 441 free(aclp, M_ACL); 442} | 566 567 return (aclp); 568} 569 570void 571acl_free(struct acl *aclp) 572{ 573 574 free(aclp, M_ACL); 575} |