From 95863bfb5e547132c8f02c49a2bed1ec308d8f5e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 5 Jan 2010 10:42:38 +0100 Subject: s3: Add vfs_linux_xfs_sgid http://oss.sgi.com/bugzilla/show_bug.cgi?id=280 shows an old Linux XFS bug that still exists: Under certain circumstances the SGID bit is not inherited. --- source3/modules/vfs_linux_xfs_sgid.c | 105 +++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 source3/modules/vfs_linux_xfs_sgid.c (limited to 'source3/modules/vfs_linux_xfs_sgid.c') diff --git a/source3/modules/vfs_linux_xfs_sgid.c b/source3/modules/vfs_linux_xfs_sgid.c new file mode 100644 index 0000000000..e01b2d1157 --- /dev/null +++ b/source3/modules/vfs_linux_xfs_sgid.c @@ -0,0 +1,105 @@ +/* + * Module to work around a bug in Linux XFS: + * http://oss.sgi.com/bugzilla/show_bug.cgi?id=280 + * + * Copyright (c) Volker Lendecke 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 . + */ + +#include "includes.h" + +static int linux_xfs_sgid_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode) +{ + struct smb_filename fname = { 0, }; + int mkdir_res; + int res; + + DEBUG(10, ("Calling linux_xfs_sgid_mkdir(%s)\n", path)); + + mkdir_res = SMB_VFS_NEXT_MKDIR(handle, path, mode); + if (mkdir_res == -1) { + DEBUG(10, ("SMB_VFS_NEXT_MKDIR returned error: %s\n", + strerror(errno))); + return mkdir_res; + } + + if (!parent_dirname(talloc_tos(), path, &fname.base_name, NULL)) { + DEBUG(1, ("parent_dirname failed\n")); + /* return success, we did the mkdir */ + return mkdir_res; + } + + res = SMB_VFS_NEXT_STAT(handle, &fname); + if (res == -1) { + DEBUG(10, ("NEXT_STAT(%s) failed: %s\n", fname.base_name, + strerror(errno))); + /* return success, we did the mkdir */ + return mkdir_res; + } + TALLOC_FREE(fname.base_name); + if ((fname.st.st_ex_mode & S_ISGID) == 0) { + /* No SGID to inherit */ + DEBUG(10, ("No SGID to inherit\n")); + return mkdir_res; + } + + fname.base_name = discard_const_p(char, path); + + res = SMB_VFS_NEXT_STAT(handle, &fname); + if (res == -1) { + DEBUG(2, ("Could not stat just created dir %s: %s\n", path, + strerror(errno))); + /* return success, we did the mkdir */ + return mkdir_res; + } + fname.st.st_ex_mode |= S_ISGID; + fname.st.st_ex_mode &= ~S_IFDIR; + + /* + * Yes, we have to do this as root. If you do it as + * non-privileged user, XFS on Linux will just ignore us and + * return success. What can you do... + */ + become_root(); + res = SMB_VFS_NEXT_CHMOD(handle, path, fname.st.st_ex_mode); + unbecome_root(); + + if (res == -1) { + DEBUG(2, ("CHMOD(%s, %o) failed: %s\n", path, + (int)fname.st.st_ex_mode, strerror(errno))); + /* return success, we did the mkdir */ + return mkdir_res; + } + return mkdir_res; +} + +static int linux_xfs_sgid_chmod_acl(vfs_handle_struct *handle, + const char *name, mode_t mode) +{ + errno = ENOSYS; + return -1; +} + +static struct vfs_fn_pointers linux_xfs_sgid_fns = { + .mkdir = linux_xfs_sgid_mkdir, + .chmod_acl = linux_xfs_sgid_chmod_acl, +}; + +NTSTATUS vfs_linux_xfs_sgid_init(void); +NTSTATUS vfs_linux_xfs_sgid_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, + "linux_xfs_sgid", &linux_xfs_sgid_fns); +} -- cgit