samba-cvs.cvs
[Top] [All Lists]

[SCM] Samba Shared Repository - branch master updated

Subject: [SCM] Samba Shared Repository - branch master updated
From: Andrew Tridgell
Date: Fri, 5 Mar 2010 06:29:09 -0600 CST
The branch, master has been updated
       via  e878880... s4-pvfs_sys: build on systems without O_NOFOLLOW or 
O_DIRECTORY
       via  568f085... s4-pvfs_sys: talloc_free should be before errno restore
       via  2c2156e... s4-pvfs: use pvfs_sys_fchmod()
       via  dae9d20... s4-pvfs: set default for perm override based on system 
features
       via  f7c97c8... s4-pvfs: use O_FOLLOW one level at a time for security 
overrides
       via  f3c738f... replace: added get_current_dir_name()
       via  ace6d75... s4-pvfs: use pvfs_sys_*() functions to wrap posix calls
       via  034bcaf... s4-pvfs: new pvfs_sys module
       via  edd5a57... s4-pvfs: added new pvfs flag PVFS_FLAG_PERM_OVERRIDE
       via  ee4ae0e... s4-privs: add root_privileges_original_uid()
      from  6c52a37... s3-selftest: enable RPC-WINREG against Samba 3.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit e8788808da604e867c8e1b31349abdd934a6789f
Author: Andrew Tridgell <tridge@xxxxxxxxx>
Date:   Fri Mar 5 23:07:26 2010 +1100

    s4-pvfs_sys: build on systems without O_NOFOLLOW or O_DIRECTORY

commit 568f0851f0fceca1511b689040340e19ef1b538b
Author: Andrew Tridgell <tridge@xxxxxxxxx>
Date:   Fri Mar 5 22:58:18 2010 +1100

    s4-pvfs_sys: talloc_free should be before errno restore
    
    talloc can potentially change the errno

commit 2c2156ea9539a818625b0914aa2e1596571f428f
Author: Andrew Tridgell <tridge@xxxxxxxxx>
Date:   Fri Mar 5 22:48:09 2010 +1100

    s4-pvfs: use pvfs_sys_fchmod()

commit dae9d20e14cafb7b688a7aa3f3680dafd727fa3f
Author: Andrew Tridgell <tridge@xxxxxxxxx>
Date:   Fri Mar 5 22:47:50 2010 +1100

    s4-pvfs: set default for perm override based on system features
    
    If the system has O_NOFOLLOW and O_DIRECTORY then we allow for
    overrides by default. If not, then we disable by default, as we will
    be more vulnerable to symlink attacks

commit f7c97c8597a2ac375983909c26027abde060edb4
Author: Andrew Tridgell <tridge@xxxxxxxxx>
Date:   Fri Mar 5 22:46:44 2010 +1100

    s4-pvfs: use O_FOLLOW one level at a time for security overrides
    
    To prevent symlink attacks we need to use O_NOFOLLOW one level at a
    time when processing a root security override

commit f3c738f8193665a80835471f6754a66b20725afa
Author: Andrew Tridgell <tridge@xxxxxxxxx>
Date:   Fri Mar 5 22:45:27 2010 +1100

    replace: added get_current_dir_name()

commit ace6d75ae6f953b76fa9709857af4744020cd6fb
Author: Andrew Tridgell <tridge@xxxxxxxxx>
Date:   Fri Mar 5 17:52:35 2010 +1100

    s4-pvfs: use pvfs_sys_*() functions to wrap posix calls
    
    This allows for root override, which fixes many problems with
    mismatches between NT ACL permissions and unix permissions.
    
    Pair-Programmed-With: Andrew Bartlett <abartlet@xxxxxxxxx>

commit 034bcaf14d1bc651c8b51b489aebcfa392158f2c
Author: Andrew Tridgell <tridge@xxxxxxxxx>
Date:   Fri Mar 5 17:51:12 2010 +1100

    s4-pvfs: new pvfs_sys module
    
    The pvfs_sys_*() calls provide wrapper functions for posix file
    functions which use root privileges to override EACCES failures if
    PVFS_FLAG_PERM_OVERRIDE is set
    
    Pair-Programmed-With: Andrew Bartlett <abartlet@xxxxxxxxx>

commit edd5a572d8f5d94511013e55744fcde48b16a3eb
Author: Andrew Tridgell <tridge@xxxxxxxxx>
Date:   Fri Mar 5 17:50:18 2010 +1100

    s4-pvfs: added new pvfs flag PVFS_FLAG_PERM_OVERRIDE
    
    This flag indicates that we should use root privileges to override
    unix permissions when the NT ACLs indicate that access should be
    granted
    
    Pair-Programmed-With: Andrew Bartlett <abartlet@xxxxxxxxx>

commit ee4ae0e7add840e1702b5630e6d23be19833a612
Author: Andrew Tridgell <tridge@xxxxxxxxx>
Date:   Fri Mar 5 17:49:11 2010 +1100

    s4-privs: add root_privileges_original_uid()
    
    This can be used to get the uid we changed away from when we gained
    root privileges
    
    Pair-Programmed-With: Andrew Bartlett <abartlet@xxxxxxxxx>

-----------------------------------------------------------------------

Summary of changes:
 lib/replace/libreplace.m4              |    1 +
 lib/replace/replace.c                  |   12 +
 lib/replace/replace.h                  |    5 +
 lib/util/unix_privs.c                  |    6 +
 source4/ntvfs/posix/config.mk          |    1 +
 source4/ntvfs/posix/pvfs_mkdir.c       |   12 +-
 source4/ntvfs/posix/pvfs_open.c        |   16 +-
 source4/ntvfs/posix/pvfs_rename.c      |    2 +-
 source4/ntvfs/posix/pvfs_setfileinfo.c |    4 +-
 source4/ntvfs/posix/pvfs_sys.c         |  638 ++++++++++++++++++++++++++++++++
 source4/ntvfs/posix/pvfs_unlink.c      |    2 +-
 source4/ntvfs/posix/pvfs_util.c        |   12 +-
 source4/ntvfs/posix/vfs_posix.c        |   10 +
 source4/ntvfs/posix/vfs_posix.h        |    2 +
 14 files changed, 699 insertions(+), 24 deletions(-)
 create mode 100644 source4/ntvfs/posix/pvfs_sys.c


Changeset truncated at 500 lines:

diff --git a/lib/replace/libreplace.m4 b/lib/replace/libreplace.m4
index c8cd213..8b7a56e 100644
--- a/lib/replace/libreplace.m4
+++ b/lib/replace/libreplace.m4
@@ -109,6 +109,7 @@ AC_CHECK_FUNCS(vsyslog setlinebuf mktime ftruncate chsize 
rename)
 AC_CHECK_FUNCS(waitpid wait4 strlcpy strlcat initgroups memmove strdup)
 AC_CHECK_FUNCS(pread pwrite strndup strcasestr strtok_r mkdtemp dup2 dprintf 
vdprintf)
 AC_CHECK_FUNCS(isatty chown lchown link readlink symlink realpath fdatasync)
+AC_CHECK_FUNCS(get_current_dir_name)
 AC_HAVE_DECL(setresuid, [#include <unistd.h>])
 AC_HAVE_DECL(setresgid, [#include <unistd.h>])
 AC_HAVE_DECL(errno, [#include <errno.h>])
diff --git a/lib/replace/replace.c b/lib/replace/replace.c
index 8eba98a..f2dcb10 100644
--- a/lib/replace/replace.c
+++ b/lib/replace/replace.c
@@ -735,3 +735,15 @@ int dprintf(int fd, const char *format, ...)
 }
 #endif
 
+#ifndef HAVE_GET_CURRENT_DIR_NAME
+char *rep_get_current_dir_name(void)
+{
+       char buf[PATH_MAX+1];
+       char *p;
+       p = getcwd(buf, sizeof(buf));
+       if (p == NULL) {
+               return NULL;
+       }
+       return strdup(p);
+}
+#endif
diff --git a/lib/replace/replace.h b/lib/replace/replace.h
index a4ef231..e7578cd 100644
--- a/lib/replace/replace.h
+++ b/lib/replace/replace.h
@@ -497,6 +497,11 @@ ssize_t rep_pwrite(int __fd, const void *__buf, size_t 
__nbytes, off_t __offset)
 /* prototype is in "system/network.h" */
 #endif
 
+#ifndef HAVE_GET_CURRENT_DIR_NAME
+#define get_current_dir_name rep_get_current_dir_name
+char *rep_get_current_dir_name(void);
+#endif
+
 #ifdef HAVE_LIMITS_H
 #include <limits.h>
 #endif
diff --git a/lib/util/unix_privs.c b/lib/util/unix_privs.c
index b30b2f5..9aa9a45 100644
--- a/lib/util/unix_privs.c
+++ b/lib/util/unix_privs.c
@@ -85,3 +85,9 @@ void *root_privileges(void)
        talloc_set_destructor(s, privileges_destructor);
        return s;
 }
+
+uid_t root_privileges_original_uid(void *s)
+{
+       struct saved_state *saved = talloc_get_type_abort(s, struct 
saved_state);
+       return saved->uid;
+}
diff --git a/source4/ntvfs/posix/config.mk b/source4/ntvfs/posix/config.mk
index bf8b573..cf4398b 100644
--- a/source4/ntvfs/posix/config.mk
+++ b/source4/ntvfs/posix/config.mk
@@ -72,6 +72,7 @@ ntvfs_posix_OBJ_FILES = $(addprefix $(ntvfssrcdir)/posix/, \
                pvfs_xattr.o \
                pvfs_streams.o \
                pvfs_notify.o \
+               pvfs_sys.o \
                xattr_system.o \
                xattr_tdb.o)
 
diff --git a/source4/ntvfs/posix/pvfs_mkdir.c b/source4/ntvfs/posix/pvfs_mkdir.c
index 6ec9e60..10de1d6 100644
--- a/source4/ntvfs/posix/pvfs_mkdir.c
+++ b/source4/ntvfs/posix/pvfs_mkdir.c
@@ -51,7 +51,7 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs,
 
        mode = pvfs_fileperms(pvfs, FILE_ATTRIBUTE_DIRECTORY);
 
-       if (mkdir(name->full_name, mode) == -1) {
+       if (pvfs_sys_mkdir(pvfs, name->full_name, mode) == -1) {
                return pvfs_map_errno(pvfs, errno);
        }
 
@@ -69,7 +69,7 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs,
        /* setup an inherited acl from the parent */
        status = pvfs_acl_inherit(pvfs, req, name, -1);
        if (!NT_STATUS_IS_OK(status)) {
-               rmdir(name->full_name);
+               pvfs_sys_rmdir(pvfs, name->full_name);
                return status;
        }
 
@@ -78,7 +78,7 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs,
                                         md->t2mkdir.in.num_eas,
                                         md->t2mkdir.in.eas);
        if (!NT_STATUS_IS_OK(status)) {
-               rmdir(name->full_name);
+               pvfs_sys_rmdir(pvfs, name->full_name);
                return status;
        }
 
@@ -127,7 +127,7 @@ NTSTATUS pvfs_mkdir(struct ntvfs_module_context *ntvfs,
 
        mode = pvfs_fileperms(pvfs, FILE_ATTRIBUTE_DIRECTORY);
 
-       if (mkdir(name->full_name, mode) == -1) {
+       if (pvfs_sys_mkdir(pvfs, name->full_name, mode) == -1) {
                return pvfs_map_errno(pvfs, errno);
        }
 
@@ -136,7 +136,7 @@ NTSTATUS pvfs_mkdir(struct ntvfs_module_context *ntvfs,
        /* setup an inherited acl from the parent */
        status = pvfs_acl_inherit(pvfs, req, name, -1);
        if (!NT_STATUS_IS_OK(status)) {
-               rmdir(name->full_name);
+               pvfs_sys_rmdir(pvfs, name->full_name);
                return status;
        }
 
@@ -179,7 +179,7 @@ NTSTATUS pvfs_rmdir(struct ntvfs_module_context *ntvfs,
                return status;
        }
 
-       if (rmdir(name->full_name) == -1) {
+       if (pvfs_sys_rmdir(pvfs, name->full_name) == -1) {
                /* some olders systems don't return ENOTEMPTY to rmdir() */
                if (errno == EEXIST) {
                        return NT_STATUS_DIRECTORY_NOT_EMPTY;
diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index d9d0d21..da32c7f 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -73,7 +73,7 @@ static int pvfs_dir_handle_destructor(struct pvfs_file_handle 
*h)
                                DEBUG(0,("Warning: xattr unlink hook failed for 
'%s' - %s\n",
                                         delete_path, nt_errstr(status)));
                        }
-                       if (rmdir(delete_path) != 0) {
+                       if (pvfs_sys_rmdir(h->pvfs, delete_path) != 0) {
                                DEBUG(0,("pvfs_dir_handle_destructor: failed to 
rmdir '%s' - %s\n",
                                         delete_path, strerror(errno)));
                        }
@@ -344,7 +344,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
                uint32_t attrib = io->generic.in.file_attr | 
FILE_ATTRIBUTE_DIRECTORY;
                mode_t mode = pvfs_fileperms(pvfs, attrib);
 
-               if (mkdir(name->full_name, mode) == -1) {
+               if (pvfs_sys_mkdir(pvfs, name->full_name, mode) == -1) {
                        return pvfs_map_errno(pvfs,errno);
                }
 
@@ -432,7 +432,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
        return NT_STATUS_OK;
 
 cleanup_delete:
-       rmdir(name->full_name);
+       pvfs_sys_rmdir(pvfs, name->full_name);
        return status;
 }
 
@@ -514,7 +514,7 @@ static int pvfs_handle_destructor(struct pvfs_file_handle 
*h)
                                DEBUG(0,("Warning: xattr unlink hook failed for 
'%s' - %s\n",
                                         delete_path, nt_errstr(status)));
                        }
-                       if (unlink(delete_path) != 0) {
+                       if (pvfs_sys_unlink(h->pvfs, delete_path) != 0) {
                                DEBUG(0,("pvfs_close: failed to delete '%s' - 
%s\n",
                                         delete_path, strerror(errno)));
                        } else {
@@ -677,7 +677,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
        mode = pvfs_fileperms(pvfs, attrib);
 
        /* create the file */
-       fd = open(name->full_name, flags | O_CREAT | O_EXCL| O_NONBLOCK, mode);
+       fd = pvfs_sys_open(pvfs, name->full_name, flags | O_CREAT | O_EXCL| 
O_NONBLOCK, mode);
        if (fd == -1) {
                return pvfs_map_errno(pvfs, errno);
        }
@@ -856,7 +856,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
 
 cleanup_delete:
        close(fd);
-       unlink(name->full_name);
+       pvfs_sys_unlink(pvfs, name->full_name);
        return status;
 }
 
@@ -1549,7 +1549,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
        }
 
        /* do the actual open */
-       fd = open(f->handle->name->full_name, flags | O_NONBLOCK);
+       fd = pvfs_sys_open(pvfs, f->handle->name->full_name, flags | 
O_NONBLOCK, 0);
        if (fd == -1) {
                status = pvfs_map_errno(f->pvfs, errno);
 
@@ -1625,7 +1625,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
                mode_t mode = pvfs_fileperms(pvfs, attrib);
                if (f->handle->name->st.st_mode != mode &&
                    f->handle->name->dos.attrib != attrib &&
-                   fchmod(fd, mode) == -1) {
+                   pvfs_sys_fchmod(pvfs, fd, mode) == -1) {
                        talloc_free(lck);
                        return pvfs_map_errno(pvfs, errno);
                }
diff --git a/source4/ntvfs/posix/pvfs_rename.c 
b/source4/ntvfs/posix/pvfs_rename.c
index 66c1427..e4448d3 100644
--- a/source4/ntvfs/posix/pvfs_rename.c
+++ b/source4/ntvfs/posix/pvfs_rename.c
@@ -37,7 +37,7 @@ NTSTATUS pvfs_do_rename(struct pvfs_state *pvfs,
        uint32_t mask;
        NTSTATUS status;
 
-       if (rename(name1->full_name, name2) == -1) {
+       if (pvfs_sys_rename(pvfs, name1->full_name, name2) == -1) {
                return pvfs_map_errno(pvfs, errno);
        }
 
diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c 
b/source4/ntvfs/posix/pvfs_setfileinfo.c
index b40ae9c..ca8e9cb 100644
--- a/source4/ntvfs/posix/pvfs_setfileinfo.c
+++ b/source4/ntvfs/posix/pvfs_setfileinfo.c
@@ -534,7 +534,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context 
*ntvfs,
                }
                mode = pvfs_fileperms(pvfs, newstats.dos.attrib);
                if (!(h->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) {
-                       if (fchmod(h->fd, mode) == -1) {
+                       if (pvfs_sys_fchmod(pvfs, h->fd, mode) == -1) {
                                return pvfs_map_errno(pvfs, errno);
                        }
                }
@@ -859,7 +859,7 @@ NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context 
*ntvfs,
        newstats.dos.attrib |= (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY);
        if (newstats.dos.attrib != name->dos.attrib) {
                mode_t mode = pvfs_fileperms(pvfs, newstats.dos.attrib);
-               if (chmod(name->full_name, mode) == -1) {
+               if (pvfs_sys_chmod(pvfs, name->full_name, mode) == -1) {
                        return pvfs_map_errno(pvfs, errno);
                }
                change_mask |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
diff --git a/source4/ntvfs/posix/pvfs_sys.c b/source4/ntvfs/posix/pvfs_sys.c
new file mode 100644
index 0000000..f110590
--- /dev/null
+++ b/source4/ntvfs/posix/pvfs_sys.c
@@ -0,0 +1,638 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   POSIX NTVFS backend - pvfs_sys wrappers
+
+   Copyright (C) Andrew Tridgell 2010
+   Copyright (C) Andrew Bartlett 2010
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "vfs_posix.h"
+#include "../lib/util/unix_privs.h"
+
+/*
+  these wrapper functions must only be called when the appropriate ACL
+  has already been checked. The wrappers will override a EACCES result
+  by gaining root privileges if the 'pvfs:perm override' is set on the
+  share (it is enabled by default)
+
+  Careful use of O_NOFOLLOW and O_DIRECTORY is used to prevent
+  security attacks via symlinks
+ */
+
+
+struct pvfs_sys_ctx {
+       struct pvfs_state *pvfs;
+       void *privs;
+       const char *old_wd;
+       struct stat st_orig;
+};
+
+
+/*
+  we create PVFS_NOFOLLOW and PVFS_DIRECTORY as aliases for O_NOFOLLOW
+  and O_DIRECTORY on systems that have them. On systems that don't
+  have O_NOFOLLOW we are less safe, but the root override code is off
+  by default.
+ */
+#ifdef O_NOFOLLOW
+#define PVFS_NOFOLLOW O_NOFOLLOW
+#else
+#define PVFS_NOFOLLOW 0
+#endif
+#ifdef O_DIRECTORY
+#define PVFS_DIRECTORY O_DIRECTORY
+#else
+#define PVFS_DIRECTORY 0
+#endif
+
+/*
+  return to original directory when context is destroyed
+ */
+static int pvfs_sys_pushdir_destructor(struct pvfs_sys_ctx *ctx)
+{
+       struct stat st;
+
+       if (ctx->old_wd == NULL) {
+               return 0;
+       }
+
+       if (chdir(ctx->old_wd) != 0) {
+               smb_panic("Failed to restore working directory");
+       }
+       if (stat(".", &st) != 0) {
+               smb_panic("Failed to stat working directory");
+       }
+       if (st.st_ino != ctx->st_orig.st_ino ||
+           st.st_dev != ctx->st_orig.st_dev) {
+               smb_panic("Working directory changed during call");
+       }
+
+       return 0;
+}
+
+
+/*
+  chdir() to the directory part of a pathname, but disallow any
+  component with a symlink
+
+  Note that we can't use O_NOFOLLOW on the whole path as that only
+  prevents links in the final component of the path
+ */
+static int pvfs_sys_chdir_nosymlink(struct pvfs_sys_ctx *ctx, const char 
*pathname)
+{
+       char *p, *path;
+       size_t base_len = strlen(ctx->pvfs->base_directory);
+
+       /* don't check for symlinks in the base directory of the share */
+       if (strncmp(ctx->pvfs->base_directory, pathname, base_len) == 0 &&
+           pathname[base_len] == '/') {
+               if (chdir(ctx->pvfs->base_directory) != 0) {
+                       return -1;
+               }
+               pathname += base_len + 1;
+       }
+
+       path = talloc_strdup(ctx, pathname);
+       if (path == NULL) {
+               return -1;
+       }
+       while ((p = strchr(path, '/'))) {
+               int fd;
+               struct stat st1, st2;
+               *p = 0;
+               fd = open(path, PVFS_NOFOLLOW | PVFS_DIRECTORY | O_RDONLY);
+               if (fd == -1) {
+                       return -1;
+               }
+               if (chdir(path) != 0) {
+                       close(fd);
+                       return -1;
+               }
+               if (stat(".", &st1) != 0 ||
+                   fstat(fd, &st2) != 0) {
+                       close(fd);
+                       return -1;
+               }
+               close(fd);
+               if (st1.st_ino != st2.st_ino ||
+                   st1.st_dev != st2.st_dev) {
+                       DEBUG(0,(__location__ ": Inode changed during chdir in 
'%s' - symlink attack?",
+                                pathname));
+                       return -1;
+               }
+               path = p + 1;
+       }
+
+       return 0;
+}
+
+
+/*
+  become root, and change directory to the directory component of a
+  path. Return a talloc context which when freed will move us back
+  to the original directory, and return us to the original uid
+
+  change the pathname argument to contain just the base component of
+  the path
+
+  return NULL on error, which could include an attempt to subvert
+  security using symlink tricks
+ */
+static struct pvfs_sys_ctx *pvfs_sys_pushdir(struct pvfs_state *pvfs,
+                                            const char **pathname)
+{
+       struct pvfs_sys_ctx *ctx;
+       char *cwd, *p, *dirname;
+       int ret;
+
+       ctx = talloc_zero(pvfs, struct pvfs_sys_ctx);
+       if (ctx == NULL) {
+               return NULL;
+       }
+       ctx->pvfs = pvfs;
+       ctx->privs = root_privileges();
+       if (ctx->privs == NULL) {
+               talloc_free(ctx);
+               return NULL;
+       }
+
+       talloc_steal(ctx, ctx->privs);
+
+       if (!pathname) {
+               /* no pathname needed */
+               return ctx;
+       }
+
+       p = strrchr(*pathname, '/');
+       if (p == NULL) {
+               /* we don't need to change directory */
+               return ctx;
+       }
+
+       /* we keep the old st around, so we can tell that
+          we have come back to the right directory */
+       if (stat(".", &ctx->st_orig) != 0) {
+               talloc_free(ctx);
+               return NULL;
+       }
+
+       cwd = get_current_dir_name();
+       if (cwd == NULL) {
+               talloc_free(ctx);
+               return NULL;
+       }
+       ctx->old_wd = talloc_strdup(ctx, cwd);
+       if (ctx->old_wd == NULL) {
+               free(cwd);
+               talloc_free(ctx);
+               return NULL;
+       }
+
+       dirname = talloc_strndup(ctx, *pathname, (p - *pathname));
+       if (dirname == NULL) {
+               talloc_free(ctx);
+               return NULL;
+       }
+
+       ret = pvfs_sys_chdir_nosymlink(ctx, *pathname);
+       if (ret == -1) {
+               talloc_free(ctx);
+               return NULL;
+       }
+
+       talloc_set_destructor(ctx, pvfs_sys_pushdir_destructor);
+
+       /* return the basename as the filename that should be operated on */
+       (*pathname) = talloc_strdup(ctx, p+1);
+       if (! *pathname) {
+               talloc_free(ctx);
+               return NULL;
+       }
+
+       return ctx;
+}
+
+
+/*
+  chown a file that we created with a root privileges override
+ */
+static int pvfs_sys_fchown(struct pvfs_state *pvfs, struct pvfs_sys_ctx *ctx, 
int fd)
+{
+       return fchown(fd, root_privileges_original_uid(ctx->privs), -1);
+}
+
+/*
+  chown a directory that we created with a root privileges override
+ */
+static int pvfs_sys_chown(struct pvfs_state *pvfs, struct pvfs_sys_ctx *ctx, 
const char *name)
+{
+       /* to avoid symlink hacks, we need to use fchown() on a directory fd */
+       int ret, fd;
+       fd = open(name, PVFS_DIRECTORY | PVFS_NOFOLLOW | O_RDONLY);
+       if (fd == -1) {
+               return -1;
+       }
+       ret = pvfs_sys_fchown(pvfs, ctx, fd);
+       close(fd);


-- 
Samba Shared Repository

<Prev in Thread] Current Thread [Next in Thread>