From e82240f4991e9211ec82bfb4f70fe776b5fde83d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= Date: Wed, 21 Mar 2012 18:42:29 +0100 Subject: [PATCH] Made sure rmdir is only used for directories, and unlink otherwise On OpenIndiana the fuse kernel module does not prevent unlink(2) from deleting directories, nor prevent rmdir(2) from deleting files, so this has to be done in the lowntfs-3g driver. --- src/lowntfs-3g.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/lowntfs-3g.c b/src/lowntfs-3g.c index 4aa6e86e..c592a65e 100644 --- a/src/lowntfs-3g.c +++ b/src/lowntfs-3g.c @@ -4,7 +4,7 @@ * Copyright (c) 2005-2007 Yura Pakhuchiy * Copyright (c) 2005 Yuval Fledel * Copyright (c) 2006-2009 Szabolcs Szakacsits - * Copyright (c) 2007-2011 Jean-Pierre Andre + * Copyright (c) 2007-2012 Jean-Pierre Andre * Copyright (c) 2009 Erik Larsson * * This file is originated from the Linux-NTFS project. @@ -191,6 +191,12 @@ enum { #endif /* defined(__sun) && defined (__SVR4) */ }; +enum RM_TYPES { + RM_LINK, + RM_DIR, + RM_ANY, +} ; + static struct ntfs_options opts; const char *EXEC_NAME = "lowntfs-3g"; @@ -216,7 +222,7 @@ static const char *usage_msg = "\n" "Copyright (C) 2005-2007 Yura Pakhuchiy\n" "Copyright (C) 2006-2009 Szabolcs Szakacsits\n" -"Copyright (C) 2007-2011 Jean-Pierre Andre\n" +"Copyright (C) 2007-2012 Jean-Pierre Andre\n" "Copyright (C) 2009 Erik Larsson\n" "\n" "Usage: %s [-o option[,...]] \n" @@ -2152,7 +2158,8 @@ static void ntfs_fuse_link(fuse_req_t req, fuse_ino_t ino, fuse_reply_entry(req, &entry); } -static int ntfs_fuse_rm(fuse_req_t req, fuse_ino_t parent, const char *name) +static int ntfs_fuse_rm(fuse_req_t req, fuse_ino_t parent, const char *name, + enum RM_TYPES rm_type __attribute__((unused))) { ntfschar *uname = NULL; ntfs_inode *dir_ni = NULL, *ni = NULL; @@ -2207,7 +2214,7 @@ static int ntfs_fuse_rm(fuse_req_t req, fuse_ino_t parent, const char *name) goto out; } /* sweep existing ghost if any */ - ntfs_fuse_rm(req, parent, ghostname); + ntfs_fuse_rm(req, parent, ghostname, RM_LINK); res = ntfs_fuse_newlink(req, of->ino, parent, ghostname, (struct fuse_entry_param*)NULL); if (res) @@ -2226,6 +2233,16 @@ static int ntfs_fuse_rm(fuse_req_t req, fuse_ino_t parent, const char *name) goto exit; } +#if defined(__sun) && defined (__SVR4) + /* on Solaris : deny unlinking directories */ + if (rm_type + == (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? RM_LINK : RM_DIR)) { + errno = EPERM; + res = -errno; + goto exit; + } +#endif /* defined(__sun) && defined (__SVR4) */ + #if !KERNELPERMS | (POSIXACLS & !KERNELACLS) /* JPA deny unlinking if directory is not writable and executable */ if (!ntfs_fuse_fill_security_context(req, &security) @@ -2256,7 +2273,7 @@ static void ntfs_fuse_unlink(fuse_req_t req, fuse_ino_t parent, { int res; - res = ntfs_fuse_rm(req, parent, name); + res = ntfs_fuse_rm(req, parent, name, RM_LINK); if (res) fuse_reply_err(req, -res); else @@ -2277,7 +2294,7 @@ static int ntfs_fuse_safe_rename(fuse_req_t req, fuse_ino_t ino, if (ret) return ret; - ret = ntfs_fuse_rm(req, newparent, newname); + ret = ntfs_fuse_rm(req, newparent, newname, RM_ANY); if (!ret) { ret = ntfs_fuse_newlink(req, ino, newparent, newname, @@ -2285,9 +2302,9 @@ static int ntfs_fuse_safe_rename(fuse_req_t req, fuse_ino_t ino, if (ret) goto restore; - ret = ntfs_fuse_rm(req, parent, name); + ret = ntfs_fuse_rm(req, parent, name, RM_ANY); if (ret) { - if (ntfs_fuse_rm(req, newparent, newname)) + if (ntfs_fuse_rm(req, newparent, newname, RM_ANY)) goto err; goto restore; } @@ -2308,7 +2325,7 @@ cleanup: * fail (unless concurrent access to directories when fuse * is multithreaded) */ - if (ntfs_fuse_rm(req, newparent, tmp) < 0) + if (ntfs_fuse_rm(req, newparent, tmp, RM_ANY) < 0) ntfs_log_perror("Rename failed. Existing file '%s' still present " "as '%s'", newname, tmp); } @@ -2429,9 +2446,9 @@ static void ntfs_fuse_rename(fuse_req_t req, fuse_ino_t parent, if (ret) goto out; - ret = ntfs_fuse_rm(req, parent, name); + ret = ntfs_fuse_rm(req, parent, name, RM_ANY); if (ret) - ntfs_fuse_rm(req, newparent, newname); + ntfs_fuse_rm(req, newparent, newname, RM_ANY); } out: if (ret) @@ -2486,7 +2503,7 @@ out: if (of) { if (of->state & CLOSE_GHOST) { sprintf(ghostname,ghostformat,of->ghost); - ntfs_fuse_rm(req, of->parent, ghostname); + ntfs_fuse_rm(req, of->parent, ghostname, RM_ANY); } /* remove from open files list */ if (of->next) @@ -2521,7 +2538,7 @@ static void ntfs_fuse_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name) { int res; - res = ntfs_fuse_rm(req, parent, name); + res = ntfs_fuse_rm(req, parent, name, RM_DIR); if (res) fuse_reply_err(req, -res); else @@ -3526,7 +3543,8 @@ static int ntfs_open(const char *device) if (ctx->hiberfile && ntfs_volume_check_hiberfile(vol, 0)) { if (errno != EPERM) goto err_out; - if (ntfs_fuse_rm((fuse_req_t)NULL,FILE_root,"hiberfil.sys")) + if (ntfs_fuse_rm((fuse_req_t)NULL,FILE_root,"hiberfil.sys", + RM_LINK)) goto err_out; }