Made a full check for whether a user extended attribute is allowed
User extended attributes should only be set on files and directories, not on symlinks, sockets, devices, etc. For safety they are also forbidden on metadata files, but should be allowed on the root directory. For files based on reparse points, requests are made to the plugin to determine the type.pull/2/head
parent
6cb8913967
commit
88451c8069
|
@ -109,6 +109,7 @@ extern int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
|
|||
void *dirent, ntfs_filldir_t filldir);
|
||||
|
||||
ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni);
|
||||
u32 ntfs_interix_types(ntfs_inode *ni);
|
||||
|
||||
int ntfs_get_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
|
||||
char *value, size_t size);
|
||||
|
|
|
@ -875,7 +875,7 @@ typedef enum {
|
|||
* and most metadata files have such similar patters.
|
||||
*/
|
||||
|
||||
static u32 ntfs_interix_types(ntfs_inode *ni)
|
||||
u32 ntfs_interix_types(ntfs_inode *ni)
|
||||
{
|
||||
ntfs_attr *na;
|
||||
u32 dt_type;
|
||||
|
@ -884,8 +884,14 @@ static u32 ntfs_interix_types(ntfs_inode *ni)
|
|||
dt_type = NTFS_DT_UNKNOWN;
|
||||
na = ntfs_attr_open(ni, AT_DATA, NULL, 0);
|
||||
if (na) {
|
||||
/* Unrecognized patterns (eg HID + SYST) are plain files */
|
||||
dt_type = NTFS_DT_REG;
|
||||
/*
|
||||
* Unrecognized patterns (eg HID + SYST for metadata)
|
||||
* are plain files or directories
|
||||
*/
|
||||
if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
|
||||
dt_type = NTFS_DT_DIR;
|
||||
else
|
||||
dt_type = NTFS_DT_REG;
|
||||
if (na->data_size <= 1) {
|
||||
if (!(ni->flags & FILE_ATTR_HIDDEN))
|
||||
dt_type = (na->data_size ?
|
||||
|
|
|
@ -3165,7 +3165,7 @@ static void ntfs_fuse_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
|
|||
goto out;
|
||||
}
|
||||
/* Return with no result for symlinks, fifo, etc. */
|
||||
if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))
|
||||
if (!user_xattrs_allowed(ctx, ni))
|
||||
goto exit;
|
||||
/* otherwise file must be readable */
|
||||
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
|
||||
|
@ -3314,7 +3314,7 @@ static void ntfs_fuse_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
|||
goto out;
|
||||
}
|
||||
/* Return with no result for symlinks, fifo, etc. */
|
||||
if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) {
|
||||
if (!user_xattrs_allowed(ctx, ni)) {
|
||||
res = -ENODATA;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -3511,7 +3511,7 @@ static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
|||
break;
|
||||
default :
|
||||
/* User xattr not allowed for symlinks, fifo, etc. */
|
||||
if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) {
|
||||
if (!user_xattrs_allowed(ctx, ni)) {
|
||||
res = -EPERM;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -3524,7 +3524,7 @@ static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
|||
#else
|
||||
/* User xattr not allowed for symlinks, fifo, etc. */
|
||||
if ((namespace == XATTRNS_USER)
|
||||
&& (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))) {
|
||||
&& !user_xattrs_allowed(ctx, ni)) {
|
||||
res = -EPERM;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -3756,7 +3756,7 @@ static void ntfs_fuse_removexattr(fuse_req_t req, fuse_ino_t ino, const char *na
|
|||
break;
|
||||
default :
|
||||
/* User xattr not allowed for symlinks, fifo, etc. */
|
||||
if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) {
|
||||
if (!user_xattrs_allowed(ctx, ni)) {
|
||||
res = -EPERM;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -3769,7 +3769,7 @@ static void ntfs_fuse_removexattr(fuse_req_t req, fuse_ino_t ino, const char *na
|
|||
#else
|
||||
/* User xattr not allowed for symlinks, fifo, etc. */
|
||||
if ((namespace == XATTRNS_USER)
|
||||
&& (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))) {
|
||||
&& !user_xattrs_allowed(ctx, ni)) {
|
||||
res = -EPERM;
|
||||
goto exit;
|
||||
}
|
||||
|
|
|
@ -2946,7 +2946,7 @@ static int ntfs_fuse_listxattr(const char *path, char *list, size_t size)
|
|||
if (!ni)
|
||||
return -errno;
|
||||
/* Return with no result for symlinks, fifo, etc. */
|
||||
if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))
|
||||
if (!user_xattrs_allowed(ctx, ni))
|
||||
goto exit;
|
||||
/* otherwise file must be readable */
|
||||
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
|
||||
|
@ -3148,7 +3148,7 @@ static int ntfs_fuse_getxattr(const char *path, const char *name,
|
|||
if (!ni)
|
||||
return -errno;
|
||||
/* Return with no result for symlinks, fifo, etc. */
|
||||
if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) {
|
||||
if (!user_xattrs_allowed(ctx, ni)) {
|
||||
res = -ENODATA;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -3324,7 +3324,7 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
|
|||
break;
|
||||
default :
|
||||
/* User xattr not allowed for symlinks, fifo, etc. */
|
||||
if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) {
|
||||
if (!user_xattrs_allowed(ctx, ni)) {
|
||||
res = -EPERM;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -3337,7 +3337,7 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
|
|||
#else
|
||||
/* User xattr not allowed for symlinks, fifo, etc. */
|
||||
if ((namespace == XATTRNS_USER)
|
||||
&& (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))) {
|
||||
&& !user_xattrs_allowed(ctx, ni)) {
|
||||
res = -EPERM;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -3561,7 +3561,7 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
|
|||
break;
|
||||
default :
|
||||
/* User xattr not allowed for symlinks, fifo, etc. */
|
||||
if (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT)) {
|
||||
if (!user_xattrs_allowed(ctx, ni)) {
|
||||
res = -EPERM;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -3574,7 +3574,7 @@ static int ntfs_fuse_removexattr(const char *path, const char *name)
|
|||
#else
|
||||
/* User xattr not allowed for symlinks, fifo, etc. */
|
||||
if ((namespace == XATTRNS_USER)
|
||||
&& (ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))) {
|
||||
&& !user_xattrs_allowed(ctx, ni)) {
|
||||
res = -EPERM;
|
||||
goto exit;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <fuse.h>
|
||||
|
||||
#include "inode.h"
|
||||
#include "dir.h"
|
||||
#include "security.h"
|
||||
#include "xattrs.h"
|
||||
#include "reparse.h"
|
||||
|
@ -862,3 +863,60 @@ void close_reparse_plugins(ntfs_fuse_context_t *ctx)
|
|||
}
|
||||
|
||||
#endif /* PLUGINS_DISABLED */
|
||||
|
||||
#ifdef HAVE_SETXATTR
|
||||
|
||||
/*
|
||||
* Check whether a user xattr is allowed
|
||||
*
|
||||
* The inode must be a plain file or a directory. The only allowed
|
||||
* metadata file is the root directory (useful for MacOSX and hopefully
|
||||
* does not harm Windows).
|
||||
*/
|
||||
|
||||
BOOL user_xattrs_allowed(ntfs_fuse_context_t *ctx, ntfs_inode *ni)
|
||||
{
|
||||
u32 dt_type;
|
||||
BOOL res;
|
||||
|
||||
/* Quick return for common cases and root */
|
||||
if (!(ni->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_REPARSE_POINT))
|
||||
|| (ni->mft_no == FILE_root))
|
||||
res = TRUE;
|
||||
else {
|
||||
/* Reparse point depends on kind, see plugin */
|
||||
if (ni->flags & FILE_ATTR_REPARSE_POINT) {
|
||||
#ifndef PLUGINS_DISABLED
|
||||
struct stat stbuf;
|
||||
REPARSE_POINT *reparse;
|
||||
const plugin_operations_t *ops;
|
||||
|
||||
res = FALSE; /* default for error cases */
|
||||
ops = select_reparse_plugin(ctx, ni, &reparse);
|
||||
if (ops) {
|
||||
if (ops->getattr
|
||||
&& !ops->getattr(ni,reparse,&stbuf)) {
|
||||
res = S_ISREG(stbuf.st_mode)
|
||||
|| S_ISDIR(stbuf.st_mode);
|
||||
}
|
||||
free(reparse);
|
||||
#else /* PLUGINS_DISABLED */
|
||||
res = FALSE; /* mountpoints, symlinks, ... */
|
||||
#endif /* PLUGINS_DISABLED */
|
||||
}
|
||||
} else {
|
||||
/* Metadata */
|
||||
if (ni->mft_no < FILE_first_user)
|
||||
res = FALSE;
|
||||
else {
|
||||
/* Interix types */
|
||||
dt_type = ntfs_interix_types(ni);
|
||||
res = (dt_type == NTFS_DT_REG)
|
||||
|| (dt_type == NTFS_DT_DIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
||||
#endif /* HAVE_SETXATTR */
|
||||
|
|
|
@ -208,6 +208,7 @@ const struct plugin_operations *select_reparse_plugin(ntfs_fuse_context_t *ctx,
|
|||
ntfs_inode *ni, REPARSE_POINT **reparse);
|
||||
int register_reparse_plugin(ntfs_fuse_context_t *ctx, le32 tag,
|
||||
const plugin_operations_t *ops, void *handle);
|
||||
BOOL user_xattrs_allowed(ntfs_fuse_context_t *ctx, ntfs_inode *ni);
|
||||
|
||||
#endif /* PLUGINS_DISABLED */
|
||||
|
||||
|
|
Loading…
Reference in New Issue