From a258817a0a1caaa20d552447e1db0f3c55ebf246 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 17 Apr 2014 16:07:50 -0600
Subject: [PATCH] server: Unify the retrieval of security attributes for files
 and directories. (try 7)

---
 server/change.c | 32 +++++---------------------------
 server/file.c   | 32 +++++++++++++++++++++-----------
 server/file.h   |  2 ++
 3 files changed, 28 insertions(+), 38 deletions(-)

diff --git a/server/change.c b/server/change.c
index 1e27e266fc1..77c9ff8bc2d 100644
--- a/server/change.c
+++ b/server/change.c
@@ -333,39 +333,17 @@ static struct fd *dir_get_fd( struct object *obj )
     return (struct fd *)grab_object( dir->fd );
 }
 
-static int get_dir_unix_fd( struct dir *dir )
-{
-    return get_unix_fd( dir->fd );
-}
-
 static struct security_descriptor *dir_get_sd( struct object *obj )
 {
     struct dir *dir = (struct dir *)obj;
-    int unix_fd;
-    struct stat st;
     struct security_descriptor *sd;
-    assert( obj->ops == &dir_ops );
-
-    unix_fd = get_dir_unix_fd( dir );
-
-    if (unix_fd == -1 || fstat( unix_fd, &st ) == -1)
-        return obj->sd;
-
-    /* mode and uid the same? if so, no need to re-generate security descriptor */
-    if (obj->sd &&
-        (st.st_mode & (S_IRWXU|S_IRWXO)) == (dir->mode & (S_IRWXU|S_IRWXO)) &&
-        (st.st_uid == dir->uid))
-        return obj->sd;
+    struct fd *fd;
 
-    sd = mode_to_sd( st.st_mode,
-                     security_unix_uid_to_sid( st.st_uid ),
-                     token_get_primary_group( current->process->token ));
-    if (!sd) return obj->sd;
+    assert( obj->ops == &dir_ops );
 
-    dir->mode = st.st_mode;
-    dir->uid = st.st_uid;
-    free( obj->sd );
-    obj->sd = sd;
+    fd = dir_get_fd( obj );
+    sd = get_file_sd( obj, fd, &dir->mode, &dir->uid );
+    release_object( fd );
     return sd;
 }
 
diff --git a/server/file.c b/server/file.c
index 34da2168643..60a47106da4 100644
--- a/server/file.c
+++ b/server/file.c
@@ -450,23 +450,19 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
     return sd;
 }
 
-static struct security_descriptor *file_get_sd( struct object *obj )
+struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode_t *mode,
+                                         uid_t *uid )
 {
-    struct file *file = (struct file *)obj;
+    int unix_fd = get_unix_fd( fd );
     struct stat st;
-    int unix_fd;
     struct security_descriptor *sd;
 
-    assert( obj->ops == &file_ops );
-
-    unix_fd = get_file_unix_fd( file );
-
     if (unix_fd == -1 || fstat( unix_fd, &st ) == -1)
         return obj->sd;
 
     /* mode and uid the same? if so, no need to re-generate security descriptor */
-    if (obj->sd && (st.st_mode & (S_IRWXU|S_IRWXO)) == (file->mode & (S_IRWXU|S_IRWXO)) &&
-        (st.st_uid == file->uid))
+    if (obj->sd && (st.st_mode & (S_IRWXU|S_IRWXO)) == (*mode & (S_IRWXU|S_IRWXO)) &&
+        (st.st_uid == *uid))
         return obj->sd;
 
     sd = mode_to_sd( st.st_mode,
@@ -474,13 +470,27 @@ static struct security_descriptor *file_get_sd( struct object *obj )
                      token_get_primary_group( current->process->token ));
     if (!sd) return obj->sd;
 
-    file->mode = st.st_mode;
-    file->uid = st.st_uid;
+    *mode = st.st_mode;
+    *uid = st.st_uid;
     free( obj->sd );
     obj->sd = sd;
     return sd;
 }
 
+static struct security_descriptor *file_get_sd( struct object *obj )
+{
+    struct file *file = (struct file *)obj;
+    struct security_descriptor *sd;
+    struct fd *fd;
+
+    assert( obj->ops == &file_ops );
+
+    fd = file_get_fd( obj );
+    sd = get_file_sd( obj, fd, &file->mode, &file->uid );
+    release_object( fd );
+    return sd;
+}
+
 static mode_t file_access_to_mode( unsigned int access )
 {
     mode_t mode = 0;
diff --git a/server/file.h b/server/file.h
index d241927ebbd..acabcc875b7 100644
--- a/server/file.h
+++ b/server/file.h
@@ -153,6 +153,8 @@ extern mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner
 extern int is_file_executable( const char *name );
 extern int set_file_sd( struct object *obj, struct fd *fd, mode_t *mode, uid_t *uid,
                         const struct security_descriptor *sd, unsigned int set_info );
+extern struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode_t *mode,
+                                                uid_t *uid );
 
 /* file mapping functions */
 
-- 
2.17.1

