diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsacl.c | 77 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 23 | ||||
-rw-r--r-- | fs/cifs/connect.c | 2 |
3 files changed, 79 insertions, 23 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index f1215df7fbee..bd75a3b8caff 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -223,6 +223,17 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
223 | le32_to_cpu(pdacl->num_aces))); | 223 | le32_to_cpu(pdacl->num_aces))); |
224 | #endif | 224 | #endif |
225 | 225 | ||
226 | /* reset rwx permissions for user/group/other. | ||
227 | Also, if num_aces is 0 i.e. DACL has no ACEs, | ||
228 | user/group/other have no permissions */ | ||
229 | inode->i_mode &= ~(S_IRWXUGO); | ||
230 | |||
231 | if (!pdacl) { | ||
232 | /* no DACL in the security descriptor, set | ||
233 | all the permissions for user/group/other */ | ||
234 | inode->i_mode |= S_IRWXUGO; | ||
235 | return; | ||
236 | } | ||
226 | acl_base = (char *)pdacl; | 237 | acl_base = (char *)pdacl; |
227 | acl_size = sizeof(struct cifs_acl); | 238 | acl_size = sizeof(struct cifs_acl); |
228 | 239 | ||
@@ -235,9 +246,6 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
235 | cifscred->aces = kmalloc(num_aces * | 246 | cifscred->aces = kmalloc(num_aces * |
236 | sizeof(struct cifs_ace *), GFP_KERNEL);*/ | 247 | sizeof(struct cifs_ace *), GFP_KERNEL);*/ |
237 | 248 | ||
238 | /* reset rwx permissions for user/group/other */ | ||
239 | inode->i_mode &= ~(S_IRWXUGO); | ||
240 | |||
241 | for (i = 0; i < num_aces; ++i) { | 249 | for (i = 0; i < num_aces; ++i) { |
242 | ppace[i] = (struct cifs_ace *) (acl_base + acl_size); | 250 | ppace[i] = (struct cifs_ace *) (acl_base + acl_size); |
243 | #ifdef CONFIG_CIFS_DEBUG2 | 251 | #ifdef CONFIG_CIFS_DEBUG2 |
@@ -309,6 +317,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
309 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; | 317 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; |
310 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ | 318 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ |
311 | char *end_of_acl = ((char *)pntsd) + acl_len; | 319 | char *end_of_acl = ((char *)pntsd) + acl_len; |
320 | __u32 dacloffset; | ||
312 | 321 | ||
313 | if ((inode == NULL) || (pntsd == NULL)) | 322 | if ((inode == NULL) || (pntsd == NULL)) |
314 | return -EIO; | 323 | return -EIO; |
@@ -317,15 +326,14 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
317 | le32_to_cpu(pntsd->osidoffset)); | 326 | le32_to_cpu(pntsd->osidoffset)); |
318 | group_sid_ptr = (struct cifs_sid *)((char *)pntsd + | 327 | group_sid_ptr = (struct cifs_sid *)((char *)pntsd + |
319 | le32_to_cpu(pntsd->gsidoffset)); | 328 | le32_to_cpu(pntsd->gsidoffset)); |
320 | dacl_ptr = (struct cifs_acl *)((char *)pntsd + | 329 | dacloffset = le32_to_cpu(pntsd->dacloffset); |
321 | le32_to_cpu(pntsd->dacloffset)); | 330 | dacl_ptr = (struct cifs_acl *)(char *)pntsd + dacloffset; |
322 | #ifdef CONFIG_CIFS_DEBUG2 | 331 | #ifdef CONFIG_CIFS_DEBUG2 |
323 | cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x " | 332 | cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x " |
324 | "sacloffset 0x%x dacloffset 0x%x", | 333 | "sacloffset 0x%x dacloffset 0x%x", |
325 | pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset), | 334 | pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset), |
326 | le32_to_cpu(pntsd->gsidoffset), | 335 | le32_to_cpu(pntsd->gsidoffset), |
327 | le32_to_cpu(pntsd->sacloffset), | 336 | le32_to_cpu(pntsd->sacloffset), dacloffset)); |
328 | le32_to_cpu(pntsd->dacloffset))); | ||
329 | #endif | 337 | #endif |
330 | /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */ | 338 | /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */ |
331 | rc = parse_sid(owner_sid_ptr, end_of_acl); | 339 | rc = parse_sid(owner_sid_ptr, end_of_acl); |
@@ -336,7 +344,11 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
336 | if (rc) | 344 | if (rc) |
337 | return rc; | 345 | return rc; |
338 | 346 | ||
339 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr, inode); | 347 | if (dacloffset) |
348 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, | ||
349 | group_sid_ptr, inode); | ||
350 | else | ||
351 | cFYI(1, ("no ACL")); /* BB grant all or default perms? */ | ||
340 | 352 | ||
341 | /* cifscred->uid = owner_sid_ptr->rid; | 353 | /* cifscred->uid = owner_sid_ptr->rid; |
342 | cifscred->gid = group_sid_ptr->rid; | 354 | cifscred->gid = group_sid_ptr->rid; |
@@ -350,9 +362,9 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
350 | } | 362 | } |
351 | 363 | ||
352 | 364 | ||
353 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ | 365 | /* Retrieve an ACL from the server */ |
354 | 366 | static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, | |
355 | void acl_to_uid_mode(struct inode *inode, const char *path) | 367 | const char *path) |
356 | { | 368 | { |
357 | struct cifsFileInfo *open_file; | 369 | struct cifsFileInfo *open_file; |
358 | int unlock_file = FALSE; | 370 | int unlock_file = FALSE; |
@@ -362,19 +374,18 @@ void acl_to_uid_mode(struct inode *inode, const char *path) | |||
362 | struct super_block *sb; | 374 | struct super_block *sb; |
363 | struct cifs_sb_info *cifs_sb; | 375 | struct cifs_sb_info *cifs_sb; |
364 | struct cifs_ntsd *pntsd = NULL; | 376 | struct cifs_ntsd *pntsd = NULL; |
365 | __u32 acllen; | ||
366 | 377 | ||
367 | cFYI(1, ("get mode from ACL for %s", path)); | 378 | cFYI(1, ("get mode from ACL for %s", path)); |
368 | 379 | ||
369 | if (inode == NULL) | 380 | if (inode == NULL) |
370 | return; | 381 | return NULL; |
371 | 382 | ||
372 | xid = GetXid(); | 383 | xid = GetXid(); |
373 | open_file = find_readable_file(CIFS_I(inode)); | 384 | open_file = find_readable_file(CIFS_I(inode)); |
374 | sb = inode->i_sb; | 385 | sb = inode->i_sb; |
375 | if (sb == NULL) { | 386 | if (sb == NULL) { |
376 | FreeXid(xid); | 387 | FreeXid(xid); |
377 | return; | 388 | return NULL; |
378 | } | 389 | } |
379 | cifs_sb = CIFS_SB(sb); | 390 | cifs_sb = CIFS_SB(sb); |
380 | 391 | ||
@@ -391,25 +402,44 @@ void acl_to_uid_mode(struct inode *inode, const char *path) | |||
391 | if (rc != 0) { | 402 | if (rc != 0) { |
392 | cERROR(1, ("Unable to open file to get ACL")); | 403 | cERROR(1, ("Unable to open file to get ACL")); |
393 | FreeXid(xid); | 404 | FreeXid(xid); |
394 | return; | 405 | return NULL; |
395 | } | 406 | } |
396 | } | 407 | } |
397 | 408 | ||
398 | rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, &acllen); | 409 | rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); |
399 | cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, acllen)); | 410 | cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); |
400 | if (unlock_file == TRUE) | 411 | if (unlock_file == TRUE) |
401 | atomic_dec(&open_file->wrtPending); | 412 | atomic_dec(&open_file->wrtPending); |
402 | else | 413 | else |
403 | CIFSSMBClose(xid, cifs_sb->tcon, fid); | 414 | CIFSSMBClose(xid, cifs_sb->tcon, fid); |
404 | 415 | ||
405 | /* parse ACEs */ | 416 | FreeXid(xid); |
406 | if (!rc) | 417 | return pntsd; |
418 | } | ||
419 | |||
420 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ | ||
421 | void acl_to_uid_mode(struct inode *inode, const char *path) | ||
422 | { | ||
423 | struct cifs_ntsd *pntsd = NULL; | ||
424 | u32 acllen = 0; | ||
425 | int rc = 0; | ||
426 | |||
427 | #ifdef CONFIG_CIFS_DEBUG2 | ||
428 | cFYI(1, ("converting ACL to mode for %s", path)); | ||
429 | #endif | ||
430 | pntsd = get_cifs_acl(&acllen, inode, path); | ||
431 | |||
432 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ | ||
433 | if (pntsd) | ||
407 | rc = parse_sec_desc(pntsd, acllen, inode); | 434 | rc = parse_sec_desc(pntsd, acllen, inode); |
435 | if (rc) | ||
436 | cFYI(1, ("parse sec desc failed rc = %d", rc)); | ||
437 | |||
408 | kfree(pntsd); | 438 | kfree(pntsd); |
409 | FreeXid(xid); | ||
410 | return; | 439 | return; |
411 | } | 440 | } |
412 | 441 | ||
442 | /* Convert mode bits to an ACL so we can update the ACL on the server */ | ||
413 | int mode_to_acl(struct inode *inode, const char *path) | 443 | int mode_to_acl(struct inode *inode, const char *path) |
414 | { | 444 | { |
415 | int rc = 0; | 445 | int rc = 0; |
@@ -419,12 +449,15 @@ int mode_to_acl(struct inode *inode, const char *path) | |||
419 | cFYI(1, ("set ACL from mode for %s", path)); | 449 | cFYI(1, ("set ACL from mode for %s", path)); |
420 | 450 | ||
421 | /* Get the security descriptor */ | 451 | /* Get the security descriptor */ |
452 | pntsd = get_cifs_acl(&acllen, inode, path); | ||
422 | 453 | ||
423 | /* Add/Modify the three ACEs for owner, group, everyone */ | 454 | /* Add/Modify the three ACEs for owner, group, everyone |
455 | while retaining the other ACEs */ | ||
424 | 456 | ||
425 | /* Set the security descriptor */ | 457 | /* Set the security descriptor */ |
426 | kfree(pntsd); | ||
427 | 458 | ||
459 | |||
460 | kfree(pntsd); | ||
428 | return rc; | 461 | return rc; |
429 | } | 462 | } |
430 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 463 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 07464b6ac129..dbe6b846f37f 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -1228,6 +1228,29 @@ typedef struct smb_com_transaction_qsec_req { | |||
1228 | __le32 AclFlags; | 1228 | __le32 AclFlags; |
1229 | } __attribute__((packed)) QUERY_SEC_DESC_REQ; | 1229 | } __attribute__((packed)) QUERY_SEC_DESC_REQ; |
1230 | 1230 | ||
1231 | |||
1232 | typedef struct smb_com_transaction_ssec_req { | ||
1233 | struct smb_hdr hdr; /* wct = 19 */ | ||
1234 | __u8 MaxSetupCount; | ||
1235 | __u16 Reserved; | ||
1236 | __le32 TotalParameterCount; | ||
1237 | __le32 TotalDataCount; | ||
1238 | __le32 MaxParameterCount; | ||
1239 | __le32 MaxDataCount; | ||
1240 | __le32 ParameterCount; | ||
1241 | __le32 ParameterOffset; | ||
1242 | __le32 DataCount; | ||
1243 | __le32 DataOffset; | ||
1244 | __u8 SetupCount; /* no setup words follow subcommand */ | ||
1245 | /* SNIA spec incorrectly included spurious pad here */ | ||
1246 | __le16 SubCommand; /* 3 = SET_SECURITY_DESC */ | ||
1247 | __le16 ByteCount; /* bcc = 3 + 8 */ | ||
1248 | __u8 Pad[3]; | ||
1249 | __u16 Fid; | ||
1250 | __u16 Reserved2; | ||
1251 | __le32 AclFlags; | ||
1252 | } __attribute__((packed)) SET_SEC_DESC_REQ; | ||
1253 | |||
1231 | typedef struct smb_com_transaction_change_notify_req { | 1254 | typedef struct smb_com_transaction_change_notify_req { |
1232 | struct smb_hdr hdr; /* wct = 23 */ | 1255 | struct smb_hdr hdr; /* wct = 23 */ |
1233 | __u8 MaxSetupCount; | 1256 | __u8 MaxSetupCount; |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 19ee11f7f35a..380ee9991f20 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -793,7 +793,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
793 | vol->linux_gid = current->gid; | 793 | vol->linux_gid = current->gid; |
794 | vol->dir_mode = S_IRWXUGO; | 794 | vol->dir_mode = S_IRWXUGO; |
795 | /* 2767 perms indicate mandatory locking support */ | 795 | /* 2767 perms indicate mandatory locking support */ |
796 | vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP); | 796 | vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP); |
797 | 797 | ||
798 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ | 798 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ |
799 | vol->rw = TRUE; | 799 | vol->rw = TRUE; |