Fixed deletions from a sticky directory (on kernels >= 2.6.25)

This commit is contained in:
jpandre 2008-06-02 10:56:23 +00:00
parent 7c05f13884
commit 767b4d075c
3 changed files with 55 additions and 27 deletions

View File

@ -3747,6 +3747,7 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
int perm;
int res;
int allow;
struct stat stbuf;
/*
* Always allow for root. From the user's point of view,
@ -3784,9 +3785,13 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
&& ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0);
break;
case S_IWRITE + S_IEXEC + S_ISVTX:
if (perm & S_ISVTX)
allow = 2;
else
if (perm & S_ISVTX) {
if ((ntfs_get_owner_mode(scx,path,ni,&stbuf) >= 0)
&& (stbuf.st_uid == scx->uid))
allow = 1;
else
allow = 2;
} else
allow = ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0)
&& ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0);
break;
@ -3821,6 +3826,7 @@ BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx,
char *name;
ntfs_inode *ni;
ntfs_inode *dir_ni;
struct stat stbuf;
allow = 0;
dirpath = strdup(path);
@ -3835,16 +3841,17 @@ BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx,
dir_ni, accesstype);
ntfs_inode_close(dir_ni);
/*
* for a sticky directory, have to retry
* and check whether file itself is writeable
* for an not-owned sticky directory, have to
* check whether file itself is owned
*/
if ((accesstype == (S_IWRITE + S_IEXEC + S_ISVTX))
&& (allow == 2)) {
ni = ntfs_pathname_to_inode(scx->vol, NULL,
path);
allow = FALSE;
if (ni) {
allow = ntfs_allowed_access(scx,path,
ni, S_IWRITE);
allow = (ntfs_get_owner_mode(scx,path,ni,&stbuf) >= 0)
&& (stbuf.st_uid == scx->uid);
ntfs_inode_close(ni);
}
}

View File

@ -1,5 +1,5 @@
--- ntfsdev/ntfs-3g/src/ntfs-3g.c 2008-04-17 10:12:03.000000000 +0200
+++ ntfsacls/ntfs-3g/src/ntfs-3g.c 2008-04-20 12:26:51.000000000 +0200
--- ntfsdev/ntfs-3g/src/ntfs-3g.c 2008-06-02 10:13:23.000000000 +0200
+++ ntfsacls/ntfs-3g/src/ntfs-3g.c 2008-06-02 11:06:46.000000000 +0200
@@ -1069,9 +1069,15 @@
securid = ntfs_inherited_id(&security, dir_path,
dir_ni, S_ISDIR(type));
@ -35,7 +35,7 @@
else {
/* Adjust read-only (for Windows) */
if (perm & S_IWUSR)
@@ -1729,6 +1743,38 @@
@@ -1750,6 +1764,38 @@
ntfschar *lename = NULL;
int res, lename_len;
@ -74,7 +74,7 @@
if (ctx->streams == NF_STREAMS_INTERFACE_WINDOWS)
return ntfs_fuse_getxattr_windows(path, name, value, size);
if (ctx->streams != NF_STREAMS_INTERFACE_XATTR)
@@ -1779,6 +1825,37 @@
@@ -1800,6 +1846,37 @@
ntfschar *lename = NULL;
int res, lename_len;
@ -112,7 +112,7 @@
if (ctx->streams != NF_STREAMS_INTERFACE_XATTR)
return -EOPNOTSUPP;
if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) ||
@@ -1837,6 +1914,37 @@
@@ -1858,6 +1935,37 @@
int res = 0, lename_len;
@ -150,7 +150,7 @@
if (ctx->streams != NF_STREAMS_INTERFACE_XATTR)
return -EOPNOTSUPP;
if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) ||
--- ntfsdev/ntfs-3g/include/ntfs-3g/security.h 2008-04-17 15:02:46.000000000 +0200
--- ntfsdev/ntfs-3g/include/ntfs-3g/security.h 2008-05-30 08:53:07.000000000 +0200
+++ ntfsacls/ntfs-3g/include/ntfs-3g/security.h 2008-04-20 11:37:48.000000000 +0200
@@ -30,6 +30,8 @@
#include "inode.h"
@ -285,8 +285,8 @@
/*
* Security API for direct access to security descriptors
* based on Win32 API
--- ntfsdev/ntfs-3g/libntfs-3g/security.c 2008-04-21 15:52:57.000000000 +0200
+++ ntfsacls/ntfs-3g/libntfs-3g/security.c 2008-04-23 10:15:26.000000000 +0200
--- ntfsdev/ntfs-3g/libntfs-3g/security.c 2008-06-02 10:19:12.000000000 +0200
+++ ntfsacls/ntfs-3g/libntfs-3g/security.c 2008-06-02 10:26:10.000000000 +0200
@@ -526,6 +526,673 @@
return (ok);
}
@ -3493,7 +3493,7 @@
} else {
errno = EPERM;
res = -1; /* neither owner nor root */
@@ -3758,7 +6474,11 @@
@@ -3759,7 +6475,11 @@
if (!scx->usermapping || !scx->uid)
allow = 1;
else {
@ -3506,7 +3506,7 @@
if (perm >= 0) {
res = EACCES;
switch (accesstype) {
@@ -3873,6 +6593,10 @@
@@ -3880,6 +6600,10 @@
mode_t mode;
int perm;
int res;
@ -3517,7 +3517,7 @@
res = 0;
/* get the current owner and mode from cache or security attributes */
@@ -3882,10 +6606,23 @@
@@ -3889,10 +6613,23 @@
fileuid = cached->uid;
filegid = cached->gid;
mode = cached->mode;
@ -3541,7 +3541,7 @@
oldattr = getsecurityattr(scx->vol, path, ni);
if (oldattr) {
phead = (const SECURITY_DESCRIPTOR_RELATIVE*)
@@ -3898,6 +6635,21 @@
@@ -3905,6 +6642,21 @@
usid = (const SID*)
&oldattr[le32_to_cpu(phead->owner)];
#endif
@ -3563,7 +3563,7 @@
mode = perm = build_permissions(oldattr,
usid, gsid, ni);
if (perm >= 0) {
@@ -3905,6 +6657,7 @@
@@ -3912,6 +6664,7 @@
filegid = findgroup(scx,gsid);
} else
res = -1;
@ -3571,7 +3571,7 @@
free(oldattr);
} else
res = -1;
@@ -3926,11 +6679,19 @@
@@ -3933,11 +6686,19 @@
/* unless request originated by root */
if (uid && (fileuid != uid))
mode &= 01777;

View File

@ -1321,7 +1321,7 @@ static int ntfs_fuse_rm(const char *org_path)
}
/* JPA deny unlinking if directory is not writable and executable */
if (!ntfs_fuse_fill_security_context(&security)
|| ntfs_allowed_access(&security, path, dir_ni,
|| ntfs_allowed_dir_access(&security, org_path,
S_IEXEC + S_IWRITE + S_ISVTX)) {
if (ntfs_delete(ctx->vol, org_path, ni, dir_ni,
@ -1379,7 +1379,7 @@ static int ntfs_fuse_unlink(const char *org_path)
*/
if (!ntfs_fuse_fill_security_context(&security)
|| ntfs_allowed_dir_access(&security, path,
S_IEXEC + S_IWRITE))
S_IEXEC + S_IWRITE + S_ISVTX))
res = ntfs_fuse_rm_stream(path, stream_name, stream_name_len);
else
res = -errno;
@ -1425,7 +1425,15 @@ err:
"to '%s'", new_path, tmp);
} else {
cleanup:
ntfs_fuse_unlink(tmp);
/*
* Condition for this unlink has already been checked in
* "ntfs_fuse_rename_existing_dest()", so it should never
* fail (unless concurrent access to directories when fuse
* is multithreaded)
*/
if (ntfs_fuse_unlink(tmp) < 0)
ntfs_log_perror("Rename failed. Existing file '%s' still present "
"as '%s'", new_path, tmp);
}
return ret;
}
@ -1434,6 +1442,7 @@ static int ntfs_fuse_rename_existing_dest(const char *old_path, const char *new_
{
int ret, len;
char *tmp;
struct SECURITY_CONTEXT security;
const char *ext = ".ntfs-3g-";
ntfs_log_trace("Entering\n");
@ -1447,9 +1456,21 @@ static int ntfs_fuse_rename_existing_dest(const char *old_path, const char *new_
if (ret != len - 1) {
ntfs_log_error("snprintf failed: %d != %d\n", ret, len - 1);
ret = -EOVERFLOW;
} else
ret = ntfs_fuse_safe_rename(old_path, new_path, tmp);
} else {
/*
* Make sure existing dest can be removed.
* This is only needed if parent directory is
* sticky, because in this situation condition
* for unlinking is different from condition for
* linking
*/
if (!ntfs_fuse_fill_security_context(&security)
|| ntfs_allowed_dir_access(&security, new_path,
S_IEXEC + S_IWRITE + S_ISVTX))
ret = ntfs_fuse_safe_rename(old_path, new_path, tmp);
else
ret = -EACCES;
}
free(tmp);
return ret;
}