diff --git a/include/ntfs-3g/security.h b/include/ntfs-3g/security.h index eaa67b41..c7710ca2 100644 --- a/include/ntfs-3g/security.h +++ b/include/ntfs-3g/security.h @@ -240,26 +240,24 @@ extern le32 ntfs_security_hash(const SECURITY_DESCRIPTOR_RELATIVE *sd, int ntfs_build_mapping(struct SECURITY_CONTEXT *scx, const char *usermap_path); int ntfs_get_owner_mode(struct SECURITY_CONTEXT *scx, - const char *path, ntfs_inode *ni, struct stat*); -int ntfs_set_mode(struct SECURITY_CONTEXT *scx, - const char *path, ntfs_inode *ni, mode_t mode); -BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, - const char *path, ntfs_inode *ni); -int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, const char *path, + ntfs_inode *ni, struct stat*); +int ntfs_set_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, mode_t mode); +BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni); +int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, int accesstype); -BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, +BOOL old_ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, const char *path, int accesstype); #if POSIXACLS le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx, - uid_t uid, gid_t gid, const char *dir_path, - ntfs_inode *dir_ni, mode_t mode, BOOL isdir); + uid_t uid, gid_t gid, ntfs_inode *dir_ni, + mode_t mode, BOOL isdir); #else le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid, mode_t mode, BOOL isdir); #endif -int ntfs_set_owner(struct SECURITY_CONTEXT *scx, - const char *path, ntfs_inode *ni, uid_t uid, gid_t gid); +int ntfs_set_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, + uid_t uid, gid_t gid); #if POSIXACLS int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, uid_t uid, gid_t gid, @@ -269,7 +267,7 @@ int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, uid_t uid, gid_t gid, mode_t mode); #endif le32 ntfs_inherited_id(struct SECURITY_CONTEXT *scx, - const char *dir_path, ntfs_inode *dir_ni, BOOL fordir); + ntfs_inode *dir_ni, BOOL fordir); int ntfs_open_secure(ntfs_volume *vol); void ntfs_close_secure(struct SECURITY_CONTEXT *scx); @@ -277,28 +275,25 @@ void ntfs_close_secure(struct SECURITY_CONTEXT *scx); int ntfs_set_inherited_posix(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, uid_t uid, gid_t gid, - const char *dir_path, ntfs_inode *dir_ni, mode_t mode); -int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, - const char *name, char *value, size_t size, - ntfs_inode *ni); -int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, + ntfs_inode *dir_ni, mode_t mode); +int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, + const char *name, char *value, size_t size); +int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, const char *name, const char *value, size_t size, - int flags, ntfs_inode *ni); -int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, - const char *name, ntfs_inode *ni); + int flags); +int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, + const char *name); #endif -int ntfs_get_ntfs_acl(struct SECURITY_CONTEXT *scx, const char *path, - const char *name, char *value, size_t size, - ntfs_inode *ni); -int ntfs_set_ntfs_acl(struct SECURITY_CONTEXT *scx, const char *path, - const char *name, const char *value, size_t size, - int flags, ntfs_inode *ni); -int ntfs_get_ntfs_attrib(const char *path, - char *value, size_t size, ntfs_inode *ni); -int ntfs_set_ntfs_attrib(const char *path, - const char *value, size_t size, int flags, - ntfs_inode *ni); +int ntfs_get_ntfs_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, + char *value, size_t size); +int ntfs_set_ntfs_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, + const char *value, size_t size, int flags); + +int ntfs_get_ntfs_attrib(ntfs_inode *ni, char *value, size_t size); +int ntfs_set_ntfs_attrib(ntfs_inode *ni, + const char *value, size_t size, int flags); + /* * Security API for direct access to security descriptors diff --git a/libntfs-3g/security.c b/libntfs-3g/security.c index 147bfbaa..d0cdd77d 100644 --- a/libntfs-3g/security.c +++ b/libntfs-3g/security.c @@ -1105,7 +1105,7 @@ static int update_secur_descr(ntfs_volume *vol, * -1 if there is a problem */ -static int upgrade_secur_desc(ntfs_volume *vol, const char *path, +static int upgrade_secur_desc(ntfs_volume *vol, const char *attr, ntfs_inode *ni) { int attrsz; @@ -1116,11 +1116,11 @@ static int upgrade_secur_desc(ntfs_volume *vol, const char *path, /* * upgrade requires NTFS format v3.x * also refuse upgrading for special files + * whose number is less than FILE_first_user */ if ((vol->major_ver >= 3) - && (path[0] == '/') - && (path[1] != '$') && (path[1] != '\0')) { + && (ni->mft_no < FILE_first_user)) { attrsz = ntfs_attr_size(attr); securid = setsecurityattr(vol, (const SECURITY_DESCRIPTOR_RELATIVE*)attr, @@ -1788,8 +1788,7 @@ static char *retrievesecurityattr(ntfs_volume *vol, SII_INDEX_KEY id) * The returned descriptor is dynamically allocated and has to be freed */ -static char *getsecurityattr(ntfs_volume *vol, - const char *path, ntfs_inode *ni) +static char *getsecurityattr(ntfs_volume *vol, ntfs_inode *ni) { SII_INDEX_KEY securid; char *securattr; @@ -1815,8 +1814,8 @@ static char *getsecurityattr(ntfs_volume *vol, securattr = ntfs_attr_readall(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0, &readallsz); if (securattr && !ntfs_valid_descr(securattr, readallsz)) { - ntfs_log_error("Bad security descriptor for %s\n", - path); + ntfs_log_error("Bad security descriptor for inode %lld\n", + (long long)ni->mft_no); free(securattr); securattr = (char*)NULL; } @@ -1830,7 +1829,8 @@ static char *getsecurityattr(ntfs_volume *vol, * minimum rights, so that a real descriptor can * be created by chown or chmod */ - ntfs_log_error("No security descriptor found for %s\n",path); + ntfs_log_error("No security descriptor found for inode %lld\n", + (long long)ni->mft_no); securattr = ntfs_build_descr(0, 0, adminsid, adminsid); } return (securattr); @@ -1968,7 +1968,7 @@ static int access_check_posix(struct SECURITY_CONTEXT *scx, */ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, - const char *path, ntfs_inode * ni, mode_t request) + ntfs_inode * ni, mode_t request) { const SECURITY_DESCRIPTOR_RELATIVE *phead; const struct CACHED_PERMISSIONS *cached; @@ -1994,7 +1994,7 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, perm = 0; /* default to no permission */ isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); - securattr = getsecurityattr(scx->vol, path, ni); + securattr = getsecurityattr(scx->vol, ni); if (securattr) { phead = (const SECURITY_DESCRIPTOR_RELATIVE*) securattr; @@ -2034,7 +2034,7 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, && (perm >= 0) && (scx->vol->secure_flags & (1 << SECURITY_ADDSECURIDS))) { - upgrade_secur_desc(scx->vol, path, + upgrade_secur_desc(scx->vol, securattr, ni); /* * fetch owner and group for cacheing @@ -2068,9 +2068,8 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, * the caller is expected to issue a new call */ -int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, - const char *name, char *value, size_t size, - ntfs_inode *ni) +int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, + const char *name, char *value, size_t size) { const SECURITY_DESCRIPTOR_RELATIVE *phead; struct POSIX_SECURITY *pxdesc; @@ -2093,7 +2092,7 @@ int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, if (cached) pxdesc = cached->pxdesc; else { - securattr = getsecurityattr(scx->vol, path, ni); + securattr = getsecurityattr(scx->vol, ni); isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); if (securattr) { @@ -2124,7 +2123,7 @@ int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, && (scx->vol->secure_flags & (1 << SECURITY_ADDSECURIDS))) { upgrade_secur_desc(scx->vol, - path, securattr, ni); + securattr, ni); } #if OWNERFROMACL uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); @@ -2202,13 +2201,10 @@ int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, * Do no use as mode of the file * * returns -1 if there is a problem - * - * This is only used for checking creation of DOS file names */ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, - const char *path, ntfs_inode *ni, - mode_t request __attribute__((unused))) + ntfs_inode *ni, mode_t request) { const SECURITY_DESCRIPTOR_RELATIVE *phead; const struct CACHED_PERMISSIONS *cached; @@ -2233,7 +2229,7 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, perm = 0; /* default to no permission */ isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); - securattr = getsecurityattr(scx->vol, path, ni); + securattr = getsecurityattr(scx->vol, ni); if (securattr) { phead = (const SECURITY_DESCRIPTOR_RELATIVE*) securattr; @@ -2265,7 +2261,7 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, && (perm >= 0) && (scx->vol->secure_flags & (1 << SECURITY_ADDSECURIDS))) { - upgrade_secur_desc(scx->vol, path, + upgrade_secur_desc(scx->vol, securattr, ni); /* * fetch owner and group for cacheing @@ -2321,15 +2317,14 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, * the caller is expected to issue a new call */ -int ntfs_get_ntfs_acl(struct SECURITY_CONTEXT *scx, const char *path, - const char *name __attribute__((unused)), - char *value, size_t size, ntfs_inode *ni) +int ntfs_get_ntfs_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, + char *value, size_t size) { char *securattr; size_t outsize; outsize = 0; /* default to no data and no error */ - securattr = getsecurityattr(scx->vol, path, ni); + securattr = getsecurityattr(scx->vol, ni); if (securattr) { outsize = ntfs_attr_size(securattr); if (outsize <= size) { @@ -2346,8 +2341,7 @@ int ntfs_get_ntfs_acl(struct SECURITY_CONTEXT *scx, const char *path, */ int ntfs_get_owner_mode(struct SECURITY_CONTEXT *scx, - const char *path, ntfs_inode * ni, - struct stat *stbuf) + ntfs_inode * ni, struct stat *stbuf) { const SECURITY_DESCRIPTOR_RELATIVE *phead; char *securattr; @@ -2374,7 +2368,7 @@ int ntfs_get_owner_mode(struct SECURITY_CONTEXT *scx, perm = -1; /* default to error */ isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); - securattr = getsecurityattr(scx->vol, path, ni); + securattr = getsecurityattr(scx->vol, ni); if (securattr) { phead = (const SECURITY_DESCRIPTOR_RELATIVE*) @@ -2410,7 +2404,7 @@ int ntfs_get_owner_mode(struct SECURITY_CONTEXT *scx, && (scx->vol->secure_flags & (1 << SECURITY_ADDSECURIDS))) { upgrade_secur_desc(scx->vol, - path, securattr, ni); + securattr, ni); } #if OWNERFROMACL stbuf->st_uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); @@ -2451,8 +2445,7 @@ int ntfs_get_owner_mode(struct SECURITY_CONTEXT *scx, */ static struct POSIX_SECURITY *inherit_posix(struct SECURITY_CONTEXT *scx, - const char *dir_path, ntfs_inode *dir_ni, - mode_t mode, BOOL isdir) + ntfs_inode *dir_ni, mode_t mode, BOOL isdir) { const struct CACHED_PERMISSIONS *cached; const SECURITY_DESCRIPTOR_RELATIVE *phead; @@ -2476,7 +2469,7 @@ static struct POSIX_SECURITY *inherit_posix(struct SECURITY_CONTEXT *scx, scx->umask,isdir); } } else { - securattr = getsecurityattr(scx->vol, dir_path, dir_ni); + securattr = getsecurityattr(scx->vol, dir_ni); if (securattr) { phead = (const SECURITY_DESCRIPTOR_RELATIVE*) securattr; @@ -2506,7 +2499,7 @@ static struct POSIX_SECURITY *inherit_posix(struct SECURITY_CONTEXT *scx, if (!test_nino_flag(dir_ni, v3_Extensions) && (scx->vol->secure_flags & (1 << SECURITY_ADDSECURIDS))) { - upgrade_secur_desc(scx->vol, dir_path, + upgrade_secur_desc(scx->vol, securattr, dir_ni); /* * fetch owner and group for cacheing @@ -2534,8 +2527,8 @@ static struct POSIX_SECURITY *inherit_posix(struct SECURITY_CONTEXT *scx, */ le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx, - uid_t uid, gid_t gid, const char *dir_path, - ntfs_inode *dir_ni, mode_t mode, BOOL isdir) + uid_t uid, gid_t gid, ntfs_inode *dir_ni, + mode_t mode, BOOL isdir) { #if !FORCE_FORMAT_v1x const struct CACHED_SECURID *cached; @@ -2554,7 +2547,7 @@ le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx, #if !FORCE_FORMAT_v1x - pxdesc = inherit_posix(scx, dir_path, dir_ni, mode, isdir); + pxdesc = inherit_posix(scx, dir_ni, mode, isdir); if (pxdesc) { /* check whether target securid is known in cache */ @@ -2617,7 +2610,7 @@ le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx, int ntfs_set_inherited_posix(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, uid_t uid, gid_t gid, - const char *dir_path, ntfs_inode *dir_ni, mode_t mode) + ntfs_inode *dir_ni, mode_t mode) { struct POSIX_SECURITY *pxdesc; char *newattr; @@ -2630,7 +2623,7 @@ int ntfs_set_inherited_posix(struct SECURITY_CONTEXT *scx, res = -1; isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); - pxdesc = inherit_posix(scx, dir_path, dir_ni, mode, isdir); + pxdesc = inherit_posix(scx, dir_ni, mode, isdir); if (pxdesc) { usid = ntfs_find_usid(scx->mapping[MAPUSERS],uid,(SID*)&defusid); gsid = ntfs_find_gsid(scx->mapping[MAPGROUPS],gid,(SID*)&defgsid); @@ -2882,8 +2875,7 @@ int ntfs_set_owner_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, * if not, errno tells why */ -BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, - const char *path, ntfs_inode *ni) +BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni) { const struct CACHED_PERMISSIONS *cached; char *oldattr; @@ -2909,7 +2901,7 @@ BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, uid = cached->uid; gotowner = TRUE; } else { - oldattr = getsecurityattr(scx->vol,path, ni); + oldattr = getsecurityattr(scx->vol, ni); if (oldattr) { #if OWNERFROMACL usid = ntfs_acl_owner(oldattr); @@ -2949,9 +2941,9 @@ BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, * Returns 0, or -1 if there is a problem which errno describes */ -int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, +int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, const char *name, const char *value, size_t size, - int flags, ntfs_inode *ni) + int flags) { const SECURITY_DESCRIPTOR_RELATIVE *phead; const struct CACHED_PERMISSIONS *cached; @@ -2991,7 +2983,7 @@ int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, (const struct POSIX_ACL*)value,count,deflt); } } else { - oldattr = getsecurityattr(scx->vol,path, ni); + oldattr = getsecurityattr(scx->vol, ni); if (oldattr) { phead = (const SECURITY_DESCRIPTOR_RELATIVE*)oldattr; #if OWNERFROMACL @@ -3052,11 +3044,11 @@ int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, * Returns 0, or -1 if there is a problem which errno describes */ -int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, - const char *name, ntfs_inode *ni) +int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, + const char *name) { - return (ntfs_set_posix_acl(scx, path, name, - (const char*)NULL, 0, 0, ni)); + return (ntfs_set_posix_acl(scx, ni, name, + (const char*)NULL, 0, 0)); } #endif @@ -3067,11 +3059,8 @@ int ntfs_remove_posix_acl(struct SECURITY_CONTEXT *scx, const char *path, * Returns 0, or -1 if there is a problem */ -int ntfs_set_ntfs_acl(struct SECURITY_CONTEXT *scx, - const char *path __attribute__((unused)), - const char *name __attribute__((unused)), - const char *value, size_t size, int flags, - ntfs_inode *ni) +int ntfs_set_ntfs_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, + const char *value, size_t size, int flags) { char *attr; int res; @@ -3130,8 +3119,7 @@ int ntfs_set_ntfs_acl(struct SECURITY_CONTEXT *scx, * -1 on failure, with errno = EIO */ -int ntfs_set_mode(struct SECURITY_CONTEXT *scx, - const char *path, ntfs_inode *ni, mode_t mode) +int ntfs_set_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, mode_t mode) { const SECURITY_DESCRIPTOR_RELATIVE *phead; const struct CACHED_PERMISSIONS *cached; @@ -3172,7 +3160,7 @@ int ntfs_set_mode(struct SECURITY_CONTEXT *scx, newpxdesc = (struct POSIX_SECURITY*)NULL; #endif } else { - oldattr = getsecurityattr(scx->vol,path, ni); + oldattr = getsecurityattr(scx->vol, ni); if (oldattr) { phead = (const SECURITY_DESCRIPTOR_RELATIVE*)oldattr; #if OWNERFROMACL @@ -3319,7 +3307,7 @@ int ntfs_sd_add_everyone(ntfs_inode *ni) */ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, - const char *path, ntfs_inode *ni, + ntfs_inode *ni, int accesstype) /* access type required (S_Ixxx values) */ { int perm; @@ -3327,10 +3315,6 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, int allow; struct stat stbuf; -#if POSIXACLS - /* shortcut, use only if Posix ACLs in use */ - if (scx->vol->secure_flags & (1 << SECURITY_DEFAULT)) return (1); -#endif /* * Always allow for root unless execution is requested. * (was checked by fuse until kernel 2.6.29) @@ -3342,7 +3326,7 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, || (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)))) allow = 1; else { - perm = ntfs_get_perm(scx, path, ni, accesstype); + perm = ntfs_get_perm(scx, ni, accesstype); if (perm >= 0) { res = EACCES; switch (accesstype) { @@ -3369,7 +3353,7 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, break; case S_IWRITE + S_IEXEC + S_ISVTX: if (perm & S_ISVTX) { - if ((ntfs_get_owner_mode(scx,path,ni,&stbuf) >= 0) + if ((ntfs_get_owner_mode(scx,ni,&stbuf) >= 0) && (stbuf.st_uid == scx->uid)) allow = 1; else @@ -3391,6 +3375,8 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, return (allow); } +#if 0 /* not needed any more */ + /* * Check whether user can access the parent directory * of a file in a specific way @@ -3403,7 +3389,7 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, * This is used for Posix ACL and checking creation of DOS file names */ -BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, +BOOL old_ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, const char *path, int accesstype) { int allow; @@ -3413,10 +3399,6 @@ BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, ntfs_inode *dir_ni; struct stat stbuf; -#if POSIXACLS - /* shortcut, use only if Posix ACLs in use */ - if (scx->vol->secure_flags & (1 << SECURITY_DEFAULT)) return (TRUE); -#endif allow = 0; dirpath = strdup(path); if (dirpath) { @@ -3426,7 +3408,7 @@ BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, *name = 0; dir_ni = ntfs_pathname_to_inode(scx->vol, NULL, dirpath); if (dir_ni) { - allow = ntfs_allowed_access(scx,dirpath, + allow = ntfs_allowed_access(scx, dir_ni, accesstype); ntfs_inode_close(dir_ni); /* @@ -3439,7 +3421,7 @@ BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, path); allow = FALSE; if (ni) { - allow = (ntfs_get_owner_mode(scx,path,ni,&stbuf) >= 0) + allow = (ntfs_get_owner_mode(scx,ni,&stbuf) >= 0) && (stbuf.st_uid == scx->uid); ntfs_inode_close(ni); } @@ -3450,14 +3432,16 @@ BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, return (allow); /* errno is set if not allowed */ } +#endif + /* * Define a new owner/group to a file * * returns zero if successful */ -int ntfs_set_owner(struct SECURITY_CONTEXT *scx, - const char *path, ntfs_inode *ni, uid_t uid, gid_t gid) +int ntfs_set_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, + uid_t uid, gid_t gid) { const SECURITY_DESCRIPTOR_RELATIVE *phead; const struct CACHED_PERMISSIONS *cached; @@ -3492,7 +3476,7 @@ int ntfs_set_owner(struct SECURITY_CONTEXT *scx, fileuid = 0; filegid = 0; mode = 0; - oldattr = getsecurityattr(scx->vol, path, ni); + oldattr = getsecurityattr(scx->vol, ni); if (oldattr) { isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) != const_cpu_to_le16(0); @@ -3709,7 +3693,7 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT *scx, */ le32 ntfs_inherited_id(struct SECURITY_CONTEXT *scx, - const char *dir_path, ntfs_inode *dir_ni, BOOL fordir) + ntfs_inode *dir_ni, BOOL fordir) { struct CACHED_PERMISSIONS *cached; char *parentattr; @@ -3732,7 +3716,7 @@ le32 ntfs_inherited_id(struct SECURITY_CONTEXT *scx, * Note : if parent directory has no id, it is not cacheable */ if (!securid) { - parentattr = getsecurityattr(scx->vol, dir_path, dir_ni); + parentattr = getsecurityattr(scx->vol, dir_ni); if (parentattr) { securid = build_inherited_id(scx, parentattr, fordir); @@ -3933,7 +3917,7 @@ static int ntfs_default_mapping(struct SECURITY_CONTEXT *scx) res = -1; ni = ntfs_pathname_to_inode(scx->vol, NULL, "/."); if (ni) { - securattr = getsecurityattr(scx->vol,"/.",ni); + securattr = getsecurityattr(scx->vol, ni); if (securattr) { phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr; usid = (SID*)&securattr[le32_to_cpu(phead->owner)]; @@ -4039,8 +4023,7 @@ int ntfs_build_mapping(struct SECURITY_CONTEXT *scx, const char *usermap_path) * The attribute is returned according to cpu endianness */ -int ntfs_get_ntfs_attrib(const char *path __attribute__((unused)), - char *value, size_t size, ntfs_inode *ni) +int ntfs_get_ntfs_attrib(ntfs_inode *ni, char *value, size_t size) { u32 attrib; size_t outsize; @@ -4072,9 +4055,8 @@ int ntfs_get_ntfs_attrib(const char *path __attribute__((unused)), * Returns 0, or -1 if there is a problem */ -int ntfs_set_ntfs_attrib(const char *path __attribute__((unused)), - const char *value, size_t size, int flags, - ntfs_inode *ni) +int ntfs_set_ntfs_attrib(ntfs_inode *ni, + const char *value, size_t size, int flags) { u32 attrib; le32 settable; @@ -4526,7 +4508,7 @@ int ntfs_get_file_security(struct SECURITY_API *scapi, if (scapi && (scapi->magic == MAGIC_API)) { ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path); if (ni) { - attr = getsecurityattr(scapi->security.vol, path, ni); + attr = getsecurityattr(scapi->security.vol, ni); if (attr) { if (feedsecurityattr(attr,selection, buf,buflen,psize)) { @@ -4595,7 +4577,7 @@ int ntfs_set_file_security(struct SECURITY_API *scapi, NULL, path); if (ni) { oldattr = getsecurityattr(scapi->security.vol, - path, ni); + ni); if (oldattr) { if (mergesecurityattr( scapi->security.vol, diff --git a/src/ntfs-3g.c b/src/ntfs-3g.c index 0139d346..2cc1622a 100644 --- a/src/ntfs-3g.c +++ b/src/ntfs-3g.c @@ -102,6 +102,15 @@ #include "logging.h" #include "misc.h" + /* sometimes the kernel cannot check access */ +#define ntfs_real_allowed_access(scx, ni, type) ntfs_allowed_access(scx, ni, type) +#if POSIXACLS + /* short-circuit if PERMS checked by kernel and ACLs by fs */ +#define ntfs_allowed_access(scx, ni, type) \ + ((scx)->vol->secure_flags & (1 << SECURITY_DEFAULT) \ + ? 1 : ntfs_allowed_access(scx, ni, type)) +#endif + #define set_archive(ni) (ni)->flags |= FILE_ATTR_ARCHIVE typedef enum { @@ -293,6 +302,127 @@ static BOOL ntfs_fuse_fill_security_context(struct SECURITY_CONTEXT *scx) return (ctx->security.mapping[MAPUSERS] != (struct MAPPING*)NULL); } +#if POSIXACLS + +/* + * Check access to parent directory + * + * directory and file inodes are only opened when not fed in, + * they *HAVE TO* be fed in when already open, however + * file inode is only useful when S_ISVTX is requested + * + * returns 1 if allowed, + * 0 if not allowed or some error occurred (errno tells why) + */ + +static int ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, + const char *path, ntfs_inode *dir_ni, + ntfs_inode *ni, mode_t accesstype) +{ + int allowed; + ntfs_inode *ni2; + ntfs_inode *dir_ni2; + char *dirpath; + char *name; + struct stat stbuf; + +#if POSIXACLS + /* short-circuit if PERMS checked by kernel and ACLs by fs */ + if (scx->vol->secure_flags & (1 << SECURITY_DEFAULT)) + allowed = 1; + else +#endif + if (dir_ni) + allowed = ntfs_real_allowed_access(scx, dir_ni, + accesstype); + else { + allowed = 0; + dirpath = strdup(path); + if (dirpath) { + /* the root of file system is seen as a parent of itself */ + /* is that correct ? */ + name = strrchr(dirpath, '/'); + *name = 0; + dir_ni2 = ntfs_pathname_to_inode(scx->vol, + NULL, dirpath); + if (dir_ni2) { + allowed = ntfs_real_allowed_access(scx, + dir_ni2, accesstype); + if (ntfs_inode_close(dir_ni2)) + allowed = 0; + } + free(dirpath); + } + } + /* + * for a not-owned sticky directory, have to + * check whether file itself is owned + */ + if ((accesstype == (S_IWRITE + S_IEXEC + S_ISVTX)) + && (allowed == 2)) { + if (ni) + ni2 = ni; + else + ni2 = ntfs_pathname_to_inode(scx->vol, NULL, + path); + allowed = 0; + if (ni2) { + allowed = (ntfs_get_owner_mode(scx,ni2,&stbuf) + >= 0) + && (stbuf.st_uid == scx->uid); + if (!ni) + ntfs_inode_close(ni2); + } + } + return (allowed); +} + +#endif + +/* + * Check access to parent directory + * + * for non-standard cases where access control cannot be checked by kernel + * + * no known situations where S_ISVTX is requested + * + * returns 1 if allowed, + * 0 if not allowed or some error occurred (errno tells why) + */ + +static int ntfs_allowed_real_dir_access(struct SECURITY_CONTEXT *scx, + const char *path, ntfs_inode *dir_ni, + mode_t accesstype) +{ + int allowed; + ntfs_inode *dir_ni2; + char *dirpath; + char *name; + + if (dir_ni) + allowed = ntfs_real_allowed_access(scx, dir_ni, accesstype); + else { + allowed = 0; + dirpath = strdup(path); + if (dirpath) { + /* the root of file system is seen as a parent of itself */ + /* is that correct ? */ + name = strrchr(dirpath, '/'); + *name = 0; + dir_ni2 = ntfs_pathname_to_inode(scx->vol, NULL, + dirpath); + if (dir_ni2) { + allowed = ntfs_real_allowed_access(scx, + dir_ni2, accesstype); + if (ntfs_inode_close(dir_ni2)) + allowed = 0; + } + free(dirpath); + } + } + return (allowed); +} + /** * ntfs_fuse_statfs - return information about mounted NTFS volume * @path: ignored (but fuse requires it) @@ -544,9 +674,11 @@ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf) * make sure the parent directory is searchable */ if (withusermapping - && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { - res = -EACCES; - goto exit; + && !ntfs_allowed_dir_access(&security,path, + (!strcmp(org_path,"/") ? ni : (ntfs_inode*)NULL), + ni, S_IEXEC)) { + res = -EACCES; + goto exit; } #endif if (((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) @@ -686,7 +818,7 @@ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf) stbuf->st_mode |= (0777 & ~ctx->fmask); } if (withusermapping) { - if (ntfs_get_owner_mode(&security,path,ni,stbuf) < 0) + if (ntfs_get_owner_mode(&security,ni,stbuf) < 0) set_fuse_error(&res); } else { stbuf->st_uid = ctx->uid; @@ -882,10 +1014,17 @@ static int ntfs_fuse_opendir(const char *path, accesstype = S_IWRITE | S_IREAD; else accesstype = S_IREAD; - /* directory must be searchable */ - if (!ntfs_allowed_dir_access(&security,path,S_IEXEC) - /* check whether requested access is allowed */ - || !ntfs_allowed_access(&security,path,ni,accesstype)) + /* + * directory must be searchable + * and requested access be allowed + */ + if (!strcmp(path,"/") + ? !ntfs_allowed_dir_access(&security, + path, ni, ni, accesstype | S_IEXEC) + : !ntfs_allowed_dir_access(&security, path, + (ntfs_inode*)NULL, ni, S_IEXEC) + || !ntfs_allowed_access(&security, + ni,accesstype)) res = -EACCES; } if (ntfs_inode_close(ni)) @@ -954,12 +1093,14 @@ static int ntfs_fuse_open(const char *org_path, accesstype = S_IWRITE | S_IREAD; else accesstype = S_IREAD; - /* JPA directory must be searchable */ + /* + * directory must be searchable + * and requested access allowed + */ if (!ntfs_allowed_dir_access(&security, - path,S_IEXEC) - /* JPA check whether requested access is allowed */ + path,(ntfs_inode*)NULL,ni,S_IEXEC) || !ntfs_allowed_access(&security, - path,ni,accesstype)) + ni,accesstype)) res = -EACCES; } #endif @@ -1188,9 +1329,10 @@ static int ntfs_fuse_trunc(const char *org_path, off_t size, * or cannot write to file (already checked for ftruncate()) */ if (ntfs_fuse_fill_security_context(&security) - && (!ntfs_allowed_dir_access(&security, path, S_IEXEC) + && (!ntfs_allowed_dir_access(&security, path, + (ntfs_inode*)NULL, ni, S_IEXEC) || (chkwrite - && !ntfs_allowed_access(&security, path, ni, S_IWRITE)))) { + && !ntfs_allowed_access(&security, ni, S_IWRITE)))) { errno = EACCES; goto exit; } @@ -1265,13 +1407,14 @@ static int ntfs_fuse_chmod(const char *path, } else { #if POSIXACLS /* parent directory must be executable */ - if (ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + if (ntfs_allowed_dir_access(&security,path, + (ntfs_inode*)NULL,(ntfs_inode*)NULL,S_IEXEC)) { #endif ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!ni) res = -errno; else { - if (ntfs_set_mode(&security,path,ni,mode)) + if (ntfs_set_mode(&security,ni,mode)) res = -errno; else ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME); @@ -1307,14 +1450,15 @@ static int ntfs_fuse_chown(const char *path, uid_t uid, gid_t gid) #if POSIXACLS /* parent directory must be executable */ - if (ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + if (ntfs_allowed_dir_access(&security,path, + (ntfs_inode*)NULL,(ntfs_inode*)NULL,S_IEXEC)) { #endif ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!ni) res = -errno; else { if (ntfs_set_owner(&security, - path,ni,uid,gid)) + ni,uid,gid)) res = -errno; else ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME); @@ -1349,8 +1493,9 @@ static int ntfs_fuse_access(const char *path, int type) else res = -EOPNOTSUPP; } else { - /* parent directory must be readable */ - if (ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + /* parent directory must be seachable */ + if (ntfs_allowed_dir_access(&security,path,(ntfs_inode*)NULL, + (ntfs_inode*)NULL,S_IEXEC)) { ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!ni) { res = -errno; @@ -1361,7 +1506,7 @@ static int ntfs_fuse_access(const char *path, int type) if (type & W_OK) mode += S_IWRITE; if (type & R_OK) mode += S_IREAD; if (!ntfs_allowed_access(&security, - path, ni, mode)) + ni, mode)) res = -errno; } if (ntfs_inode_close(ni)) @@ -1419,7 +1564,7 @@ static int ntfs_fuse_create(const char *org_path, mode_t typemode, dev_t dev, #if POSIXACLS /* make sure parent directory is writeable and executable */ if (!ntfs_fuse_fill_security_context(&security) - || ntfs_allowed_access(&security,dir_path, + || ntfs_allowed_access(&security, dir_ni,S_IWRITE + S_IEXEC)) { #else ntfs_fuse_fill_security_context(&security); @@ -1438,13 +1583,13 @@ static int ntfs_fuse_create(const char *org_path, mode_t typemode, dev_t dev, securid = 0; else if (ctx->inherit) - securid = ntfs_inherited_id(&security, dir_path, + securid = ntfs_inherited_id(&security, dir_ni, S_ISDIR(type)); else #if POSIXACLS securid = ntfs_alloc_securid(&security, security.uid, security.gid, - dir_path, dir_ni, perm, S_ISDIR(type)); + dir_ni, perm, S_ISDIR(type)); #else securid = ntfs_alloc_securid(&security, security.uid, security.gid, @@ -1482,7 +1627,7 @@ static int ntfs_fuse_create(const char *org_path, mode_t typemode, dev_t dev, if (!securid && ntfs_set_inherited_posix(&security, ni, security.uid, security.gid, - dir_path, dir_ni, perm) < 0) + dir_ni, perm) < 0) set_fuse_error(&res); #else if (!securid @@ -1630,6 +1775,7 @@ static int ntfs_fuse_link(const char *old_path, const char *new_path) char *path; int res = 0, uname_len; #if POSIXACLS + BOOL samedir; struct SECURITY_CONTEXT security; #endif @@ -1664,10 +1810,13 @@ static int ntfs_fuse_link(const char *old_path, const char *new_path) } #if POSIXACLS + samedir = !strncmp(old_path, path, strlen(path)) + && (old_path[strlen(path)] == '/'); /* JPA make sure the parent directories are writeable */ if (ntfs_fuse_fill_security_context(&security) - && (!ntfs_allowed_dir_access(&security,old_path,S_IWRITE + S_IEXEC) - || !ntfs_allowed_access(&security,path,dir_ni,S_IWRITE + S_IEXEC))) + && ((!samedir && !ntfs_allowed_dir_access(&security,old_path, + (ntfs_inode*)NULL,ni,S_IWRITE + S_IEXEC)) + || !ntfs_allowed_access(&security,dir_ni,S_IWRITE + S_IEXEC))) res = -EACCES; else #endif @@ -1734,7 +1883,7 @@ static int ntfs_fuse_rm(const char *org_path) #if POSIXACLS /* JPA deny unlinking if directory is not writable and executable */ if (!ntfs_fuse_fill_security_context(&security) - || ntfs_allowed_dir_access(&security, org_path, + || ntfs_allowed_dir_access(&security, org_path, dir_ni, ni, S_IEXEC + S_IWRITE + S_ISVTX)) { #endif if (ntfs_delete(ctx->vol, org_path, ni, dir_ni, @@ -1797,8 +1946,10 @@ static int ntfs_fuse_unlink(const char *org_path) */ if (!ntfs_fuse_fill_security_context(&security) || ntfs_allowed_dir_access(&security, path, + (ntfs_inode*)NULL, (ntfs_inode*)NULL, S_IEXEC + S_IWRITE + S_ISVTX)) - res = ntfs_fuse_rm_stream(path, stream_name, stream_name_len); + res = ntfs_fuse_rm_stream(path, stream_name, + stream_name_len); else res = -errno; #else @@ -1890,6 +2041,7 @@ static int ntfs_fuse_rename_existing_dest(const char *old_path, const char *new_ */ if (!ntfs_fuse_fill_security_context(&security) || ntfs_allowed_dir_access(&security, new_path, + (ntfs_inode*)NULL, (ntfs_inode*)NULL, S_IEXEC + S_IWRITE + S_ISVTX)) ret = ntfs_fuse_safe_rename(old_path, new_path, tmp); else @@ -2003,17 +2155,19 @@ static int ntfs_fuse_utime(const char *path, struct utimbuf *buf) if (ntfs_fuse_is_named_data_stream(path)) return -EINVAL; /* n/a for named data streams. */ #if POSIXACLS - /* parent directory must be executable */ + /* parent directory must be executable */ if (ntfs_fuse_fill_security_context(&security) - && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + && !ntfs_allowed_dir_access(&security,path, + (ntfs_inode*)NULL,(ntfs_inode*)NULL,S_IEXEC)) { return (-errno); } #endif ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!ni) return -errno; + #if POSIXACLS - ownerok = ntfs_allowed_as_owner(&security, path, ni); + ownerok = ntfs_allowed_as_owner(&security, ni); if (buf) { /* * fuse never calls with a NULL buf and we do not @@ -2023,7 +2177,7 @@ static int ntfs_fuse_utime(const char *path, struct utimbuf *buf) */ writeok = !ownerok && (buf->actime == buf->modtime) - && ntfs_allowed_access(&security, path, ni, S_IWRITE); + && ntfs_allowed_access(&security, ni, S_IWRITE); /* Must be owner */ if (!ownerok && !writeok) res = (buf->actime == buf->modtime ? -EACCES : -EPERM); @@ -2035,7 +2189,7 @@ static int ntfs_fuse_utime(const char *path, struct utimbuf *buf) } else { /* Must be owner or have write access */ writeok = !ownerok - && ntfs_allowed_access(&security, path, ni, S_IWRITE); + && ntfs_allowed_access(&security, ni, S_IWRITE); if (!ownerok && !writeok) res = -EACCES; else @@ -2205,8 +2359,15 @@ static ntfs_inode *ntfs_check_access_xattr(struct SECURITY_CONTEXT *security, acctype = S_IEXEC | S_IWRITE; else acctype = S_IEXEC; - if (ntfs_allowed_dir_access(security,path,acctype)) { - ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); + if ((attr == XATTR_NTFS_DOS_NAME) + && !strcmp(path,"/")) + /* forbid getting/setting names on root */ + errno = EPERM; + else + if (ntfs_allowed_real_dir_access(security, path, + (ntfs_inode*)NULL ,acctype)) { + ni = ntfs_pathname_to_inode(ctx->vol, + NULL, path); } } } @@ -2317,7 +2478,8 @@ static int ntfs_fuse_listxattr(const char *path, char *list, size_t size) #if POSIXACLS /* parent directory must be executable */ if (ntfs_fuse_fill_security_context(&security) - && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + && !ntfs_allowed_dir_access(&security,path,(ntfs_inode*)NULL, + (ntfs_inode*)NULL,S_IEXEC)) { return (-errno); } #endif @@ -2326,7 +2488,7 @@ static int ntfs_fuse_listxattr(const char *path, char *list, size_t size) return -errno; #if POSIXACLS /* file must be readable */ - if (!ntfs_allowed_access(&security,path,ni,S_IREAD)) { + if (!ntfs_allowed_access(&security,ni,S_IREAD)) { ret = -EACCES; goto exit; } @@ -2427,7 +2589,8 @@ static int ntfs_fuse_getxattr_windows(const char *path, const char *name, #if POSIXACLS /* parent directory must be executable */ if (ntfs_fuse_fill_security_context(&security) - && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + && !ntfs_allowed_dir_access(&security,path,(ntfs_inode*)NULL, + (ntfs_inode*)NULL,S_IEXEC)) { return (-errno); } #endif @@ -2435,7 +2598,7 @@ static int ntfs_fuse_getxattr_windows(const char *path, const char *name, if (!ni) return -errno; #if POSIXACLS - if (!ntfs_allowed_access(&security,path,ni,S_IREAD)) { + if (!ntfs_allowed_access(&security,ni,S_IREAD)) { ret = -errno; goto exit; } @@ -2509,9 +2672,9 @@ static int ntfs_fuse_getxattr(const char *path, const char *name, * mode was selected for xattr (from the user's * point of view, ACLs are not xattr) */ - ni = ntfs_check_access_xattr(&security,path,attr,FALSE); + ni = ntfs_check_access_xattr(&security, path, attr, FALSE); if (ni) { - if (ntfs_allowed_access(&security,path,ni,S_IREAD)) { + if (ntfs_allowed_access(&security,ni,S_IREAD)) { /* * the returned value is the needed * size. If it is too small, no copy @@ -2520,17 +2683,17 @@ static int ntfs_fuse_getxattr(const char *path, const char *name, */ switch (attr) { case XATTR_NTFS_ACL : - res = ntfs_get_ntfs_acl(&security,path, - name,value,size,ni); + res = ntfs_get_ntfs_acl(&security, ni, + value, size); break; case XATTR_POSIX_ACC : case XATTR_POSIX_DEF : - res = ntfs_get_posix_acl(&security,path, - name,value,size,ni); + res = ntfs_get_posix_acl(&security, ni, + name, value, size); break; case XATTR_NTFS_ATTRIB : - res = ntfs_get_ntfs_attrib(path, - value,size,ni); + res = ntfs_get_ntfs_attrib(ni, + value, size); break; case XATTR_NTFS_EFSINFO : if (ctx->efs_raw) @@ -2551,7 +2714,13 @@ static int ntfs_fuse_getxattr(const char *path, const char *name, res = ntfs_inode_get_times(path, value,size,ni); break; - default : /* not possible */ + default : + /* + * make sure applications do not see + * Posix ACL not consistent with mode + */ + errno = EOPNOTSUPP; + res = -errno; break; } } else { @@ -2582,12 +2751,12 @@ static int ntfs_fuse_getxattr(const char *path, const char *name, */ switch (attr) { case XATTR_NTFS_ACL : - res = ntfs_get_ntfs_acl(&security,path, - name,value,size,ni); + res = ntfs_get_ntfs_acl(&security, ni, + value, size); break; case XATTR_NTFS_ATTRIB : - res = ntfs_get_ntfs_attrib(path, - value,size,ni); + res = ntfs_get_ntfs_attrib(ni, + value, size); break; case XATTR_NTFS_EFSINFO : if (ctx->efs_raw) @@ -2635,7 +2804,8 @@ static int ntfs_fuse_getxattr(const char *path, const char *name, #if POSIXACLS /* parent directory must be executable */ if (ntfs_fuse_fill_security_context(&security) - && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + && !ntfs_allowed_dir_access(&security,path,(ntfs_inode*)NULL, + (ntfs_inode*)NULL,S_IEXEC)) { return (-errno); } /* trusted only readable by root */ @@ -2648,7 +2818,7 @@ static int ntfs_fuse_getxattr(const char *path, const char *name, return -errno; #if POSIXACLS /* file must be readable */ - if (!ntfs_allowed_access(&security, path, ni, S_IREAD)) { + if (!ntfs_allowed_access(&security, ni, S_IREAD)) { res = -errno; goto exit; } @@ -2709,20 +2879,20 @@ static int ntfs_fuse_setxattr(const char *path, const char *name, */ ni = ntfs_check_access_xattr(&security,path,attr,TRUE); if (ni) { - if (ntfs_allowed_as_owner(&security,path,ni)) { + if (ntfs_allowed_as_owner(&security,ni)) { switch (attr) { case XATTR_NTFS_ACL : - res = ntfs_set_ntfs_acl(&security,path, - name,value,size,flags,ni); + res = ntfs_set_ntfs_acl(&security, ni, + value, size, flags); break; case XATTR_POSIX_ACC : case XATTR_POSIX_DEF : - res = ntfs_set_posix_acl(&security,path, - name,value,size,flags,ni); + res = ntfs_set_posix_acl(&security, ni, + name, value, size, flags); break; case XATTR_NTFS_ATTRIB : - res = ntfs_set_ntfs_attrib(path, - value,size,flags,ni); + res = ntfs_set_ntfs_attrib(ni, + value, size, flags); break; case XATTR_NTFS_EFSINFO : if (ctx->efs_raw) @@ -2744,7 +2914,13 @@ static int ntfs_fuse_setxattr(const char *path, const char *name, res = ntfs_inode_set_times(path, value,size,flags,ni); break; - default : /* not possible */ + default : + /* + * make sure applications do not see + * Posix ACL not consistent with mode + */ + errno = EOPNOTSUPP; + res = -errno; break; } if (res) @@ -2776,15 +2952,15 @@ static int ntfs_fuse_setxattr(const char *path, const char *name, * if defined, only owner is allowed */ if (!ntfs_fuse_fill_security_context(&security) - || ntfs_allowed_as_owner(&security,path,ni)) { + || ntfs_allowed_as_owner(&security, ni)) { switch (attr) { case XATTR_NTFS_ACL : - res = ntfs_set_ntfs_acl(&security,path, - name,value,size,flags,ni); + res = ntfs_set_ntfs_acl(&security, ni, + value, size, flags); break; case XATTR_NTFS_ATTRIB : - res = ntfs_set_ntfs_attrib(path, - value,size,flags,ni); + res = ntfs_set_ntfs_attrib(ni, + value, size, flags); break; case XATTR_NTFS_EFSINFO : if (ctx->efs_raw) @@ -2837,7 +3013,8 @@ static int ntfs_fuse_setxattr(const char *path, const char *name, #if POSIXACLS /* parent directory must be executable */ if (ntfs_fuse_fill_security_context(&security) - && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + && !ntfs_allowed_dir_access(&security,path,(ntfs_inode*)NULL, + (ntfs_inode*)NULL,S_IEXEC)) { return (-errno); } /* security and trusted only settable by root */ @@ -2859,13 +3036,13 @@ static int ntfs_fuse_setxattr(const char *path, const char *name, } break; case XATTRNS_SYSTEM : - if (!ntfs_allowed_as_owner(&security,path,ni)) { + if (!ntfs_allowed_as_owner(&security,ni)) { res = -EACCES; goto exit; } break; default : - if (!ntfs_allowed_access(&security,path,ni,S_IWRITE)) { + if (!ntfs_allowed_access(&security,ni,S_IWRITE)) { res = -EACCES; goto exit; } @@ -2968,9 +3145,9 @@ static int ntfs_fuse_removexattr(const char *path, const char *name) case XATTR_POSIX_DEF : ni = ntfs_check_access_xattr(&security,path,attr,TRUE); if (ni) { - if (!ntfs_allowed_as_owner(&security,path,ni) - || ntfs_remove_posix_acl(&security,path, - name,ni)) + if (!ntfs_allowed_as_owner(&security, ni) + || ntfs_remove_posix_acl(&security, ni, + name)) res = -errno; if (ntfs_inode_close(ni)) set_fuse_error(&res); @@ -2980,7 +3157,7 @@ static int ntfs_fuse_removexattr(const char *path, const char *name) case XATTR_NTFS_REPARSE_DATA : ni = ntfs_check_access_xattr(&security,path,attr,TRUE); if (ni) { - if (!ntfs_allowed_as_owner(&security,path,ni) + if (!ntfs_allowed_as_owner(&security, ni) || ntfs_remove_ntfs_reparse_data(path,ni)) res = -errno; if (ntfs_inode_close(ni)) @@ -3030,7 +3207,7 @@ static int ntfs_fuse_removexattr(const char *path, const char *name) * if defined, only owner is allowed */ if ((ntfs_fuse_fill_security_context(&security) - && !ntfs_allowed_as_owner(&security,path,ni)) + && !ntfs_allowed_as_owner(&security, ni)) || ntfs_remove_ntfs_reparse_data(path,ni)) res = -errno; if (ntfs_inode_close(ni)) @@ -3068,7 +3245,8 @@ static int ntfs_fuse_removexattr(const char *path, const char *name) #if POSIXACLS /* parent directory must be executable */ if (ntfs_fuse_fill_security_context(&security) - && !ntfs_allowed_dir_access(&security,path,S_IEXEC)) { + && !ntfs_allowed_dir_access(&security,path,(ntfs_inode*)NULL, + (ntfs_inode*)NULL,S_IEXEC)) { return (-errno); } /* security and trusted only settable by root */ @@ -3090,13 +3268,13 @@ static int ntfs_fuse_removexattr(const char *path, const char *name) } break; case XATTRNS_SYSTEM : - if (!ntfs_allowed_as_owner(&security,path,ni)) { + if (!ntfs_allowed_as_owner(&security,ni)) { res = -EACCES; goto exit; } break; default : - if (!ntfs_allowed_access(&security,path,ni,S_IWRITE)) { + if (!ntfs_allowed_access(&security,ni,S_IWRITE)) { res = -EACCES; goto exit; }