~ehoover/netflix-desktop/trunk

« back to all changes in this revision

Viewing changes to wine-patches/0002-server-Store-and-return-security-attributes-with-ext.patch

  • Committer: Erich E. Hoover
  • Date: 2012-12-19 22:10:38 UTC
  • Revision ID: ehoover@mines.edu-20121219221038-guqjlefsk69o60tg
Added the patches to Wine to the repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
From 4c4235eb2a26999870adc5538e25a4a34b7d0d17 Mon Sep 17 00:00:00 2001
 
2
From: Erich Hoover <ehoover@mines.edu>
 
3
Date: Fri, 7 Dec 2012 12:55:47 -0700
 
4
Subject: server: Store and return security attributes with extended file
 
5
 attributes.
 
6
 
 
7
---
 
8
 configure.ac                    |    1 +
 
9
 dlls/advapi32/tests/security.c  |    9 +-
 
10
 dlls/kernel32/tests/directory.c |    4 +-
 
11
 server/change.c                 |   11 ++-
 
12
 server/fd.c                     |   68 ++++++++++++++-
 
13
 server/file.c                   |  176 ++++++++++++++++++++++++++++++++++++++-
 
14
 server/file.h                   |    5 +-
 
15
 7 files changed, 258 insertions(+), 16 deletions(-)
 
16
 
 
17
diff --git a/configure.ac b/configure.ac
 
18
index 01d84cd..a3521f1 100644
 
19
--- a/configure.ac
 
20
+++ b/configure.ac
 
21
@@ -417,6 +417,7 @@ AC_CHECK_HEADERS(\
 
22
        arpa/inet.h \
 
23
        arpa/nameser.h \
 
24
        asm/types.h \
 
25
+       attr/xattr.h \
 
26
        capi20.h \
 
27
        curses.h \
 
28
        direct.h \
 
29
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
 
30
index fbbbd17..4bad5d1 100644
 
31
--- a/dlls/advapi32/tests/security.c
 
32
+++ b/dlls/advapi32/tests/security.c
 
33
@@ -3155,7 +3155,7 @@ static void test_GetNamedSecurityInfoA(void)
 
34
         bret = pGetAce(pDacl, 0, (VOID **)&ace);
 
35
         ok(bret, "Failed to get Current User ACE.\n");
 
36
         bret = EqualSid(&ace->SidStart, user_sid);
 
37
-        todo_wine ok(bret, "Current User ACE != Current User SID.\n");
 
38
+        ok(bret, "Current User ACE != Current User SID.\n");
 
39
         ok(((ACE_HEADER *)ace)->AceFlags == 0,
 
40
            "Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
 
41
         ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
 
42
@@ -3166,8 +3166,7 @@ static void test_GetNamedSecurityInfoA(void)
 
43
         bret = pGetAce(pDacl, 1, (VOID **)&ace);
 
44
         ok(bret, "Failed to get Administators Group ACE.\n");
 
45
         bret = EqualSid(&ace->SidStart, admin_sid);
 
46
-        todo_wine ok(bret || broken(!bret) /* win2k */,
 
47
-                     "Administators Group ACE != Administators Group SID.\n");
 
48
+        ok(bret || broken(!bret) /* win2k */, "Administators Group ACE != Administators Group SID.\n");
 
49
         ok(((ACE_HEADER *)ace)->AceFlags == 0,
 
50
            "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
 
51
         ok(ace->Mask == 0x1f01ff || broken(ace->Mask == GENERIC_ALL) /* win2k */,
 
52
@@ -3748,7 +3747,7 @@ static void test_GetSecurityInfo(void)
 
53
         bret = pGetAce(pDacl, 0, (VOID **)&ace);
 
54
         ok(bret, "Failed to get Current User ACE.\n");
 
55
         bret = EqualSid(&ace->SidStart, user_sid);
 
56
-        todo_wine ok(bret, "Current User ACE != Current User SID.\n");
 
57
+        ok(bret, "Current User ACE != Current User SID.\n");
 
58
         ok(((ACE_HEADER *)ace)->AceFlags == 0,
 
59
            "Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
 
60
         ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
 
61
@@ -3759,7 +3758,7 @@ static void test_GetSecurityInfo(void)
 
62
         bret = pGetAce(pDacl, 1, (VOID **)&ace);
 
63
         ok(bret, "Failed to get Administators Group ACE.\n");
 
64
         bret = EqualSid(&ace->SidStart, admin_sid);
 
65
-        todo_wine ok(bret, "Administators Group ACE != Administators Group SID.\n");
 
66
+        ok(bret, "Administators Group ACE != Administators Group SID.\n");
 
67
         ok(((ACE_HEADER *)ace)->AceFlags == 0,
 
68
            "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
 
69
         ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
 
70
diff --git a/dlls/kernel32/tests/directory.c b/dlls/kernel32/tests/directory.c
 
71
index 0d286d2..99d8fd1 100644
 
72
--- a/dlls/kernel32/tests/directory.c
 
73
+++ b/dlls/kernel32/tests/directory.c
 
74
@@ -578,7 +578,7 @@ static void test_security_attributes(void)
 
75
         bret = pGetAce(pDacl, 0, (VOID **)&ace);
 
76
         ok(bret, "Failed to get Current User ACE.\n");
 
77
         bret = EqualSid(&ace->SidStart, user_sid);
 
78
-        todo_wine ok(bret, "Current User ACE != Current User SID.\n");
 
79
+        ok(bret, "Current User ACE != Current User SID.\n");
 
80
         ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
 
81
            "Current User ACE has unexpected flags (0x%x != 0x03)\n", ((ACE_HEADER *)ace)->AceFlags);
 
82
         ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
 
83
@@ -589,7 +589,7 @@ static void test_security_attributes(void)
 
84
         bret = pGetAce(pDacl, 1, (VOID **)&ace);
 
85
         ok(bret, "Failed to get Administators Group ACE.\n");
 
86
         bret = EqualSid(&ace->SidStart, admin_sid);
 
87
-        todo_wine ok(bret, "Administators Group ACE != Administators Group SID.\n");
 
88
+        ok(bret, "Administators Group ACE != Administators Group SID.\n");
 
89
         ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
 
90
            "Administators Group ACE has unexpected flags (0x%x != 0x03)\n", ((ACE_HEADER *)ace)->AceFlags);
 
91
         ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
 
92
diff --git a/server/change.c b/server/change.c
 
93
index f6d56b0..022c780 100644
 
94
--- a/server/change.c
 
95
+++ b/server/change.c
 
96
@@ -286,6 +286,7 @@ static int get_dir_unix_fd( struct dir *dir )
 
97
 static struct security_descriptor *dir_get_sd( struct object *obj )
 
98
 {
 
99
     struct dir *dir = (struct dir *)obj;
 
100
+    const SID *user, *group;
 
101
     int unix_fd;
 
102
     struct stat st;
 
103
     struct security_descriptor *sd;
 
104
@@ -302,9 +303,11 @@ static struct security_descriptor *dir_get_sd( struct object *obj )
 
105
         (st.st_uid == dir->uid))
 
106
         return obj->sd;
 
107
 
 
108
-    sd = mode_to_sd( st.st_mode,
 
109
-                     security_unix_uid_to_sid( st.st_uid ),
 
110
-                     token_get_primary_group( current->process->token ));
 
111
+    user = security_unix_uid_to_sid( st.st_uid );
 
112
+    group = token_get_primary_group( current->process->token );
 
113
+    sd = get_file_acls( unix_fd, user, group );
 
114
+    if (!sd)
 
115
+        sd = mode_to_sd( st.st_mode, user, group );
 
116
     if (!sd) return obj->sd;
 
117
 
 
118
     dir->mode = st.st_mode;
 
119
@@ -353,6 +356,8 @@ static int dir_set_sd( struct object *obj, const struct security_descriptor *sd,
 
120
         mode = st.st_mode & (S_ISUID|S_ISGID|S_ISVTX);
 
121
         mode |= sd_to_mode( sd, owner );
 
122
 
 
123
+        set_file_acls( unix_fd, sd );
 
124
+
 
125
         if (((st.st_mode ^ mode) & (S_IRWXU|S_IRWXG|S_IRWXO)) && fchmod( unix_fd, mode ) == -1)
 
126
         {
 
127
             file_set_error();
 
128
diff --git a/server/fd.c b/server/fd.c
 
129
index 248f15a..687d4a9 100644
 
130
--- a/server/fd.c
 
131
+++ b/server/fd.c
 
132
@@ -88,6 +88,9 @@
 
133
 #include <sys/time.h>
 
134
 #include <sys/types.h>
 
135
 #include <unistd.h>
 
136
+#ifdef HAVE_ATTR_XATTR_H
 
137
+#include <attr/xattr.h>
 
138
+#endif
 
139
 
 
140
 #include "ntstatus.h"
 
141
 #define WIN32_NO_STATUS
 
142
@@ -96,6 +99,7 @@
 
143
 #include "handle.h"
 
144
 #include "process.h"
 
145
 #include "request.h"
 
146
+#include "security.h"
 
147
 
 
148
 #include "winternl.h"
 
149
 #include "winioctl.h"
 
150
@@ -1723,9 +1727,69 @@ static char *dup_fd_name( struct fd *root, const char *name )
 
151
     return ret;
 
152
 }
 
153
 
 
154
+void set_file_acls( int fd, const struct security_descriptor *sd )
 
155
+{
 
156
+#ifdef HAVE_ATTR_XATTR_H
 
157
+    char buffer[XATTR_SIZE_MAX], *p = buffer;
 
158
+    const ACE_HEADER *ace;
 
159
+    int present, i, j, n;
 
160
+    const ACL *dacl;
 
161
+
 
162
+    if (!sd) return;
 
163
+    dacl = sd_get_dacl( sd, &present );
 
164
+    if (!present || !dacl) return;
 
165
+    ace = (const ACE_HEADER *)(dacl + 1);
 
166
+
 
167
+    for (i = 0; i < dacl->AceCount; i++, ace = ace_next( ace ))
 
168
+    {
 
169
+        BYTE type = ace->AceType, flags;
 
170
+        const ACCESS_ALLOWED_ACE *aaa;
 
171
+        const ACCESS_DENIED_ACE *ada;
 
172
+        char sidtxt[100], *s;
 
173
+        const SID *sid;
 
174
+        DWORD mask;
 
175
+
 
176
+        if (type & INHERIT_ONLY_ACE) continue;
 
177
+
 
178
+        switch (type)
 
179
+        {
 
180
+            case ACCESS_DENIED_ACE_TYPE:
 
181
+                ada   = (const ACCESS_DENIED_ACE *)ace;
 
182
+                flags = ada->Header.AceFlags;
 
183
+                mask  = ada->Mask;
 
184
+                sid   = (const SID *)&ada->SidStart;
 
185
+                break;
 
186
+            case ACCESS_ALLOWED_ACE_TYPE:
 
187
+                aaa   = (const ACCESS_ALLOWED_ACE *)ace;
 
188
+                flags = aaa->Header.AceFlags;
 
189
+                mask  = aaa->Mask;
 
190
+                sid   = (const SID *)&aaa->SidStart;
 
191
+                break;
 
192
+            default:
 
193
+                continue;
 
194
+        }
 
195
+        n = sprintf( sidtxt,  "S-%u-%d", sid->Revision,
 
196
+            MAKELONG(
 
197
+                MAKEWORD( sid->IdentifierAuthority.Value[5],
 
198
+                          sid->IdentifierAuthority.Value[4] ),
 
199
+                MAKEWORD( sid->IdentifierAuthority.Value[3],
 
200
+                          sid->IdentifierAuthority.Value[2] )
 
201
+            ) );
 
202
+        s = sidtxt + n;
 
203
+        for( j=0; j<sid->SubAuthorityCount; j++ )
 
204
+            s += sprintf( s, "-%u", sid->SubAuthority[j] );
 
205
+
 
206
+        p += snprintf( p, XATTR_SIZE_MAX-(p-buffer), "%s%x,%x,%x,%s",
 
207
+                      (p != buffer ? ";" : ""), type, flags, mask, sidtxt );
 
208
+    }
 
209
+
 
210
+    fsetxattr( fd, "user.wine.acl", buffer, p-buffer, 0 );
 
211
+#endif
 
212
+}
 
213
+
 
214
 /* open() wrapper that returns a struct fd with no fd user set */
 
215
 struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode, unsigned int access,
 
216
-                    unsigned int sharing, unsigned int options )
 
217
+                    unsigned int sharing, unsigned int options, const struct security_descriptor *sd )
 
218
 {
 
219
     struct stat st;
 
220
     struct closed_fd *closed_fd;
 
221
@@ -1801,6 +1865,8 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
 
222
         }
 
223
     }
 
224
 
 
225
+    set_file_acls( fd->unix_fd, sd );
 
226
+
 
227
     closed_fd->unix_fd = fd->unix_fd;
 
228
     closed_fd->unlink[0] = 0;
 
229
     fstat( fd->unix_fd, &st );
 
230
diff --git a/server/file.c b/server/file.c
 
231
index 3a8c964..3fd1f42 100644
 
232
--- a/server/file.c
 
233
+++ b/server/file.c
 
234
@@ -32,6 +32,7 @@
 
235
 #include <sys/time.h>
 
236
 #include <sys/types.h>
 
237
 #include <time.h>
 
238
+#include <limits.h>
 
239
 #include <unistd.h>
 
240
 #ifdef HAVE_UTIME_H
 
241
 #include <utime.h>
 
242
@@ -39,6 +40,9 @@
 
243
 #ifdef HAVE_POLL_H
 
244
 #include <poll.h>
 
245
 #endif
 
246
+#ifdef HAVE_ATTR_XATTR_H
 
247
+#include <attr/xattr.h>
 
248
+#endif
 
249
 
 
250
 #include "ntstatus.h"
 
251
 #define WIN32_NO_STATUS
 
252
@@ -240,7 +244,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
 
253
     access = generic_file_map_access( access );
 
254
 
 
255
     /* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */
 
256
-    fd = open_fd( root, name, flags | O_NONBLOCK | O_LARGEFILE, &mode, access, sharing, options );
 
257
+    fd = open_fd( root, name, flags | O_NONBLOCK | O_LARGEFILE, &mode, access, sharing, options, sd );
 
258
     if (!fd) goto done;
 
259
 
 
260
     if (S_ISDIR(mode))
 
261
@@ -435,9 +439,169 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
 
262
     return sd;
 
263
 }
 
264
 
 
265
+struct security_descriptor *get_file_acls( int fd, const SID *user, const SID *group )
 
266
+{
 
267
+#ifdef HAVE_ATTR_XATTR_H
 
268
+    int ace_count = 0, dacl_size = sizeof(ACL), i, n;
 
269
+    char buffer[XATTR_SIZE_MAX], *p = buffer, *pn;
 
270
+    struct security_descriptor *sd;
 
271
+    ACE_HEADER *current_ace;
 
272
+    ACCESS_ALLOWED_ACE *aaa;
 
273
+    ACCESS_DENIED_ACE *ada;
 
274
+    int type, flags, mask;
 
275
+    ACL *dacl;
 
276
+    char *ptr;
 
277
+
 
278
+    n = fgetxattr( fd, "user.wine.acl", buffer, sizeof(buffer) );
 
279
+    if (n == -1) return NULL;
 
280
+    buffer[n] = 0;
 
281
+
 
282
+    do
 
283
+    {
 
284
+        int sub_authority_count = 0;
 
285
+
 
286
+        pn = strchr(p, ';');
 
287
+        if (pn) pn++;
 
288
+        sscanf(p, "%x", &type);
 
289
+        do
 
290
+        {
 
291
+            p = strchr(p, '-');
 
292
+            if (p) p++;
 
293
+            sub_authority_count++;
 
294
+        }
 
295
+        while(p && (!pn || p < pn));
 
296
+        sub_authority_count -= 3; /* Revision and IdentifierAuthority don't count */
 
297
+
 
298
+        switch (type)
 
299
+        {
 
300
+            case ACCESS_DENIED_ACE_TYPE:
 
301
+                dacl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) +
 
302
+                             FIELD_OFFSET(SID, SubAuthority[sub_authority_count]);
 
303
+                break;
 
304
+            case ACCESS_ALLOWED_ACE_TYPE:
 
305
+                dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
 
306
+                             FIELD_OFFSET(SID, SubAuthority[sub_authority_count]);
 
307
+                break;
 
308
+            default:
 
309
+                continue;
 
310
+        }
 
311
+        ace_count++;
 
312
+        p = pn;
 
313
+    }
 
314
+    while(p);
 
315
+
 
316
+    sd = mem_alloc( sizeof(struct security_descriptor) +
 
317
+                    FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) +
 
318
+                    FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]) +
 
319
+                    dacl_size );
 
320
+
 
321
+    sd->control = SE_DACL_PRESENT;
 
322
+    sd->owner_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
 
323
+    sd->group_len = FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]);
 
324
+    sd->sacl_len = 0;
 
325
+    sd->dacl_len = dacl_size;
 
326
+
 
327
+    ptr = (char *)(sd + 1);
 
328
+    memcpy( ptr, user, sd->owner_len );
 
329
+    ptr += sd->owner_len;
 
330
+    memcpy( ptr, group, sd->group_len );
 
331
+    ptr += sd->group_len;
 
332
+
 
333
+    dacl = (ACL *)ptr;
 
334
+    dacl->AclRevision = ACL_REVISION;
 
335
+    dacl->Sbz1 = 0;
 
336
+    dacl->AclSize = dacl_size;
 
337
+    dacl->AceCount = ace_count;
 
338
+    dacl->Sbz2 = 0;
 
339
+    aaa = (ACCESS_ALLOWED_ACE *)(dacl + 1);
 
340
+    current_ace = &aaa->Header;
 
341
+
 
342
+    p = buffer;
 
343
+    for(i=0; i<ace_count; i++)
 
344
+    {
 
345
+        char b[sizeof(SID) + sizeof(ULONG) * SID_MAX_SUB_AUTHORITIES];
 
346
+        int sub_authority_count = 0;
 
347
+        SID *sid = (SID *)&b[0];
 
348
+        char sidtxt[100];
 
349
+        int rev, ia, sa;
 
350
+
 
351
+        if (i != 0)
 
352
+        {
 
353
+            aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
 
354
+            current_ace = &aaa->Header;
 
355
+        }
 
356
+        pn = strchr(p, ';');
 
357
+        if (pn) pn++;
 
358
+        sscanf(p, "%x,%x,%x,%[^;]", &type, &flags, &mask, sidtxt);
 
359
+        sscanf(sidtxt, "S-%u-%d", &rev, &ia);
 
360
+        sid->Revision = rev;
 
361
+        sid->IdentifierAuthority.Value[0] = 0;
 
362
+        sid->IdentifierAuthority.Value[1] = 0;
 
363
+        sid->IdentifierAuthority.Value[2] = HIBYTE(HIWORD(ia));
 
364
+        sid->IdentifierAuthority.Value[3] = LOBYTE(HIWORD(ia));
 
365
+        sid->IdentifierAuthority.Value[4] = HIBYTE(LOWORD(ia));
 
366
+        sid->IdentifierAuthority.Value[5] = LOBYTE(LOWORD(ia));
 
367
+        p = strchr(sidtxt, '-')+1; 
 
368
+        p = strchr(p, '-')+1; /* Revision doesn't count */
 
369
+        p = strchr(p, '-')+1; /* IdentifierAuthority doesn't count */
 
370
+        do
 
371
+        {
 
372
+            sscanf(p, "%u", &sa);
 
373
+            sid->SubAuthority[sub_authority_count] = sa;
 
374
+            p = strchr(p, '-');
 
375
+            if (p) p++;
 
376
+            sub_authority_count++;
 
377
+        }
 
378
+        while(p);
 
379
+        sid->SubAuthorityCount = sub_authority_count;
 
380
+
 
381
+        /* Convert generic rights into standard access rights */
 
382
+        if (mask & GENERIC_ALL)
 
383
+            mask |= WRITE_DAC | WRITE_OWNER | DELETE | FILE_DELETE_CHILD;
 
384
+        if (mask & (GENERIC_ALL|GENERIC_READ))
 
385
+            mask |= FILE_GENERIC_READ;
 
386
+        if (mask & (GENERIC_ALL|GENERIC_WRITE))
 
387
+            mask |= FILE_GENERIC_WRITE;
 
388
+        if (mask & (GENERIC_ALL|GENERIC_EXECUTE))
 
389
+            mask |= FILE_GENERIC_EXECUTE;
 
390
+        mask &= 0x0FFFFFFF;
 
391
+
 
392
+        /* Handle the specific ACE */
 
393
+        switch (type)
 
394
+        {
 
395
+            case ACCESS_DENIED_ACE_TYPE:
 
396
+                ada = (ACCESS_DENIED_ACE *)aaa;
 
397
+                ada->Header.AceType  = type;
 
398
+                ada->Header.AceFlags = flags;
 
399
+                ada->Header.AceSize  = FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) +
 
400
+                                       FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]);
 
401
+                ada->Mask            = mask;
 
402
+                memcpy( &ada->SidStart, sid, FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]) );
 
403
+                break;
 
404
+            case ACCESS_ALLOWED_ACE_TYPE:
 
405
+                aaa->Header.AceType  = type;
 
406
+                aaa->Header.AceFlags = flags;
 
407
+                aaa->Header.AceSize  = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
 
408
+                                       FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]);
 
409
+                aaa->Mask            = mask;
 
410
+                memcpy( &aaa->SidStart, sid, FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]) );
 
411
+                break;
 
412
+            default:
 
413
+                continue;
 
414
+        }
 
415
+        p = pn;
 
416
+    }
 
417
+
 
418
+    return sd;
 
419
+#else
 
420
+    return NULL;
 
421
+#endif
 
422
+}
 
423
+
 
424
 static struct security_descriptor *file_get_sd( struct object *obj )
 
425
 {
 
426
     struct file *file = (struct file *)obj;
 
427
+    const SID *user, *group;
 
428
     struct stat st;
 
429
     int unix_fd;
 
430
     struct security_descriptor *sd;
 
431
@@ -454,9 +618,11 @@ static struct security_descriptor *file_get_sd( struct object *obj )
 
432
         (st.st_uid == file->uid))
 
433
         return obj->sd;
 
434
 
 
435
-    sd = mode_to_sd( st.st_mode,
 
436
-                     security_unix_uid_to_sid( st.st_uid ),
 
437
-                     token_get_primary_group( current->process->token ));
 
438
+    user = security_unix_uid_to_sid( st.st_uid );
 
439
+    group = token_get_primary_group( current->process->token );
 
440
+    sd = get_file_acls( unix_fd, user, group );
 
441
+    if (!sd)
 
442
+        sd = mode_to_sd( st.st_mode, user, group);
 
443
     if (!sd) return obj->sd;
 
444
 
 
445
     file->mode = st.st_mode;
 
446
@@ -586,6 +752,8 @@ static int file_set_sd( struct object *obj, const struct security_descriptor *sd
 
447
         mode = st.st_mode & (S_ISUID|S_ISGID|S_ISVTX);
 
448
         mode |= sd_to_mode( sd, owner );
 
449
 
 
450
+        set_file_acls( unix_fd, sd );
 
451
+
 
452
         if (((st.st_mode ^ mode) & (S_IRWXU|S_IRWXG|S_IRWXO)) && fchmod( unix_fd, mode ) == -1)
 
453
         {
 
454
             file_set_error();
 
455
diff --git a/server/file.h b/server/file.h
 
456
index ead356d..77737e8 100644
 
457
--- a/server/file.h
 
458
+++ b/server/file.h
 
459
@@ -56,7 +56,8 @@ extern struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct obje
 
460
                                    unsigned int options );
 
461
 extern void set_no_fd_status( struct fd *fd, unsigned int status );
 
462
 extern struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
 
463
-                           unsigned int access, unsigned int sharing, unsigned int options );
 
464
+                           unsigned int access, unsigned int sharing, unsigned int options,
 
465
+                           const struct security_descriptor *sd );
 
466
 extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops,
 
467
                                        int unix_fd, struct object *user, unsigned int options );
 
468
 extern struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sharing,
 
469
@@ -122,6 +123,8 @@ extern struct file *create_file_for_fd_obj( struct fd *fd, unsigned int access,
 
470
 extern void file_set_error(void);
 
471
 extern struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID *group );
 
472
 extern mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner );
 
473
+extern void set_file_acls( int fd, const struct security_descriptor *sd );
 
474
+extern struct security_descriptor *get_file_acls( int fd, const SID *user, const SID *group );
 
475
 
 
476
 /* file mapping functions */
 
477
 
 
478
-- 
 
479
1.7.9.5
 
480