Fix the UNIX extensions CHOWN calls to use FCHOWN if available, else LCHOWN.
authorJeremy Allison <jra@samba.org>
Wed, 21 Aug 2013 19:20:48 +0000 (12:20 -0700)
committerJeremy Allison <jra@samba.org>
Mon, 26 Aug 2013 18:19:46 +0000 (20:19 +0200)
UNIX extensions calls must never deref links.

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Simo Sorce <idra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Mon Aug 26 20:19:46 CEST 2013 on sn-devel-104

source3/smbd/trans2.c

index 3cd21926b181335bc9a281a9ade1e0f89130fa8c..b6cb3cc34909600be9f0ab9fc6f53bd3081d96af 100644 (file)
@@ -7155,12 +7155,15 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
                          (unsigned int)set_owner,
                          smb_fname_str_dbg(smb_fname)));
 
-               if (S_ISLNK(sbuf.st_ex_mode)) {
+               if (fsp && fsp->fh->fd != -1) {
+                       ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
+               } else {
+                       /*
+                        * UNIX extensions calls must always operate
+                        * on symlinks.
+                        */
                        ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
                                             set_owner, (gid_t)-1);
-               } else {
-                       ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
-                                           set_owner, (gid_t)-1);
                }
 
                if (ret != 0) {
@@ -7178,12 +7181,23 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
 
        if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
            (sbuf.st_ex_gid != set_grp)) {
+               int ret;
+
                DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
                          "changing group %u for file %s\n",
                          (unsigned int)set_owner,
                          smb_fname_str_dbg(smb_fname)));
-               if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
-                                 set_grp) != 0) {
+               if (fsp && fsp->fh->fd != -1) {
+                       ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
+               } else {
+                       /*
+                        * UNIX extensions calls must always operate
+                        * on symlinks.
+                        */
+                       ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
+                                 set_grp);
+               }
+               if (ret != 0) {
                        status = map_nt_error_from_unix(errno);
                        if (delete_on_fail) {
                                SMB_VFS_UNLINK(conn, smb_fname);