diff --git a/debian/changelog b/debian/changelog index d9d6204d..9794091a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,7 @@ wine-compholio (1.7.16-1) UNRELEASED; urgency=low * Split Arial replacement into two patches. * Removed dynamic unwind patches (accepted upstream). * Removed linguistic casing patches (accepted upstream). + * ACL data is now stored in binary instead of converting it to ASCII. -- Erich E. Hoover Sat, 05 Apr 2014 17:38:41 -0600 wine-compholio (1.7.16-1) unstable; urgency=low diff --git a/patches/02-ACL_Extended_Attributes/0001-server-Unify-the-storage-of-security-attributes-for-.patch b/patches/02-ACL_Extended_Attributes/0001-server-Unify-the-storage-of-security-attributes-for-.patch index fa2b03ef..fea97603 100644 --- a/patches/02-ACL_Extended_Attributes/0001-server-Unify-the-storage-of-security-attributes-for-.patch +++ b/patches/02-ACL_Extended_Attributes/0001-server-Unify-the-storage-of-security-attributes-for-.patch @@ -1,6 +1,6 @@ -From ee79e1be71635431d0d05841c7f9cea720411ba6 Mon Sep 17 00:00:00 2001 +From 379e01b2aea67fa305d2ccd08b589d2d31cd0da0 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" -Date: Thu, 13 Feb 2014 15:45:41 -0700 +Date: Thu, 17 Apr 2014 16:07:46 -0600 Subject: server: Unify the storage of security attributes for files and directories. @@ -11,7 +11,7 @@ Subject: server: Unify the storage of security attributes for files and 3 files changed, 25 insertions(+), 48 deletions(-) diff --git a/server/change.c b/server/change.c -index f6d56b0..76fc9f7 100644 +index f6d56b0..7cea06b 100644 --- a/server/change.c +++ b/server/change.c @@ -317,49 +317,15 @@ static struct security_descriptor *dir_get_sd( struct object *obj ) @@ -64,14 +64,14 @@ index f6d56b0..76fc9f7 100644 - } - return 1; + fd = dir_get_fd( obj ); -+ ret = file_set_acls( obj, fd, sd, set_info ); ++ ret = set_file_sd( obj, fd, sd, set_info ); + release_object( fd ); + return ret; } static struct change_record *get_first_change_record( struct dir *dir ) diff --git a/server/file.c b/server/file.c -index cceb8ad..13ebaf9 100644 +index cceb8ad..fb89272 100644 --- a/server/file.c +++ b/server/file.c @@ -534,18 +534,13 @@ mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner ) @@ -80,8 +80,8 @@ index cceb8ad..13ebaf9 100644 -static int file_set_sd( struct object *obj, const struct security_descriptor *sd, - unsigned int set_info ) -+int file_set_acls( struct object *obj, struct fd *fd, const struct security_descriptor *sd, -+ unsigned int set_info ) ++int set_file_sd( struct object *obj, struct fd *fd, const struct security_descriptor *sd, ++ unsigned int set_info ) { - struct file *file = (struct file *)obj; + int unix_fd = get_unix_fd( fd ); @@ -109,7 +109,7 @@ index cceb8ad..13ebaf9 100644 + assert( obj->ops == &file_ops ); + + fd = file_get_fd( obj ); -+ ret = file_set_acls( obj, fd, sd, set_info ); ++ ret = set_file_sd( obj, fd, sd, set_info ); + release_object( fd ); + return ret; +} @@ -118,15 +118,15 @@ index cceb8ad..13ebaf9 100644 { struct file *file = (struct file *)obj; diff --git a/server/file.h b/server/file.h -index 493d30b..11c3220 100644 +index 493d30b..76cb383 100644 --- a/server/file.h +++ b/server/file.h @@ -122,6 +122,8 @@ extern struct file *create_file_for_fd_obj( struct fd *fd, unsigned int access, extern void file_set_error(void); extern struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID *group ); extern mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner ); -+extern int file_set_acls( struct object *obj, struct fd *fd, const struct security_descriptor *sd, -+ unsigned int set_info ); ++extern int set_file_sd( struct object *obj, struct fd *fd, const struct security_descriptor *sd, ++ unsigned int set_info ); /* file mapping functions */ diff --git a/patches/02-ACL_Extended_Attributes/0002-server-Unify-the-retrieval-of-security-attributes-fo.patch b/patches/02-ACL_Extended_Attributes/0002-server-Unify-the-retrieval-of-security-attributes-fo.patch index 3f89cd88..4ce0790b 100644 --- a/patches/02-ACL_Extended_Attributes/0002-server-Unify-the-retrieval-of-security-attributes-fo.patch +++ b/patches/02-ACL_Extended_Attributes/0002-server-Unify-the-retrieval-of-security-attributes-fo.patch @@ -1,6 +1,6 @@ -From bf6cb3c547ce790864af7b244f7934d3f5e3780d Mon Sep 17 00:00:00 2001 +From e20db446df6bb0177f90964cd09dd9a993d120f3 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" -Date: Tue, 15 Apr 2014 14:19:26 -0600 +Date: Thu, 17 Apr 2014 16:07:50 -0600 Subject: server: Unify the retrieval of security attributes for files and directories. @@ -11,7 +11,7 @@ Subject: server: Unify the retrieval of security attributes for files and 3 files changed, 28 insertions(+), 38 deletions(-) diff --git a/server/change.c b/server/change.c -index 76fc9f7..eb16923 100644 +index 7cea06b..c391180 100644 --- a/server/change.c +++ b/server/change.c @@ -278,39 +278,17 @@ static struct fd *dir_get_fd( struct object *obj ) @@ -54,13 +54,13 @@ index 76fc9f7..eb16923 100644 - free( obj->sd ); - obj->sd = sd; + fd = dir_get_fd( obj ); -+ sd = file_get_acls( obj, fd, &dir->mode, &dir->uid ); ++ sd = set_file_sd( obj, fd, &dir->mode, &dir->uid ); + release_object( fd ); return sd; } diff --git a/server/file.c b/server/file.c -index 13ebaf9..c98f045 100644 +index fb89272..1f008ea 100644 --- a/server/file.c +++ b/server/file.c @@ -424,23 +424,19 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID @@ -68,8 +68,8 @@ index 13ebaf9..c98f045 100644 } -static struct security_descriptor *file_get_sd( struct object *obj ) -+struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mode_t *mode, -+ uid_t *uid ) ++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 ); @@ -114,7 +114,7 @@ index 13ebaf9..c98f045 100644 + assert( obj->ops == &file_ops ); + + fd = file_get_fd( obj ); -+ sd = file_get_acls( obj, fd, &file->mode, &file->uid ); ++ sd = get_file_sd( obj, fd, &file->mode, &file->uid ); + release_object( fd ); + return sd; +} @@ -123,15 +123,15 @@ index 13ebaf9..c98f045 100644 { mode_t mode = 0; diff --git a/server/file.h b/server/file.h -index 11c3220..89b5888 100644 +index 76cb383..43a234f 100644 --- a/server/file.h +++ b/server/file.h @@ -124,6 +124,8 @@ extern struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, con extern mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner ); - extern int file_set_acls( struct object *obj, struct fd *fd, const struct security_descriptor *sd, - unsigned int set_info ); -+extern struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mode_t *mode, -+ uid_t *uid ); + extern int set_file_sd( struct object *obj, struct fd *fd, 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 */ diff --git a/patches/02-ACL_Extended_Attributes/0003-server-Store-file-security-attributes-with-extended-.patch b/patches/02-ACL_Extended_Attributes/0003-server-Store-file-security-attributes-with-extended-.patch index 1c830e61..5c4ba64e 100644 --- a/patches/02-ACL_Extended_Attributes/0003-server-Store-file-security-attributes-with-extended-.patch +++ b/patches/02-ACL_Extended_Attributes/0003-server-Store-file-security-attributes-with-extended-.patch @@ -1,16 +1,16 @@ -From be78120bae662c7290b09433b020548a2b299361 Mon Sep 17 00:00:00 2001 +From a82ce7ae33ae842f531c96cc9457a73430c45773 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" -Date: Tue, 15 Apr 2014 15:03:12 -0600 +Date: Thu, 17 Apr 2014 16:08:03 -0600 Subject: server: Store file security attributes with extended file attributes. --- - configure.ac | 12 ++++++++++ - server/file.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 83 insertions(+) + configure.ac | 12 ++++++++++++ + server/file.c | 31 +++++++++++++++++++++++++++++++ + 2 files changed, 43 insertions(+) diff --git a/configure.ac b/configure.ac -index 7e463b9..c0cc653 100644 +index 46602d6..99fcb9b 100644 --- a/configure.ac +++ b/configure.ac @@ -73,6 +73,7 @@ AC_ARG_WITH(pthread, AS_HELP_STRING([--without-pthread],[do not use the pthrea @@ -40,7 +40,7 @@ index 7e463b9..c0cc653 100644 AC_SUBST(dlldir,"\${libdir}/wine") diff --git a/server/file.c b/server/file.c -index c98f045..032205e 100644 +index 1f008ea..ceb57be 100644 --- a/server/file.c +++ b/server/file.c @@ -32,6 +32,7 @@ @@ -61,90 +61,50 @@ index c98f045..032205e 100644 #include "ntstatus.h" #define WIN32_NO_STATUS -@@ -178,6 +182,70 @@ static struct object *create_file_obj( struct fd *fd, unsigned int access, mode_ +@@ -178,6 +182,30 @@ static struct object *create_file_obj( struct fd *fd, unsigned int access, mode_ return &file->obj; } -+void set_xattr_acls( int fd, const struct security_descriptor *sd ) ++void set_xattr_sd( int fd, const struct security_descriptor *sd ) +{ +#ifdef HAVE_ATTR_XATTR_H -+ char buffer[XATTR_SIZE_MAX], *p = buffer; -+ const ACE_HEADER *ace; -+ int present, i, j, n; ++ char buffer[XATTR_SIZE_MAX]; ++ int present, len; + const ACL *dacl; + ++ /* there's no point in storing the security descriptor if there's no DACL */ + if (!sd) return; + dacl = sd_get_dacl( sd, &present ); + if (!present || !dacl) return; -+ ace = (const ACE_HEADER *)(dacl + 1); + -+ for (i = 0; i < dacl->AceCount; i++, ace = ace_next( ace )) -+ { -+ BYTE type = ace->AceType, flags; -+ const ACCESS_ALLOWED_ACE *aaa; -+ const ACCESS_DENIED_ACE *ada; -+ char sidtxt[100], *s; -+ const SID *sid; -+ DWORD mask; ++ len = 2 + sizeof(struct security_descriptor) + sd->owner_len + sd->group_len + sd->sacl_len ++ + sd->dacl_len; ++ if (len > XATTR_SIZE_MAX) return; + -+ switch (type) -+ { -+ case ACCESS_DENIED_ACE_TYPE: -+ ada = (const ACCESS_DENIED_ACE *)ace; -+ flags = ada->Header.AceFlags; -+ mask = ada->Mask; -+ sid = (const SID *)&ada->SidStart; -+ break; -+ case ACCESS_ALLOWED_ACE_TYPE: -+ aaa = (const ACCESS_ALLOWED_ACE *)ace; -+ flags = aaa->Header.AceFlags; -+ mask = aaa->Mask; -+ sid = (const SID *)&aaa->SidStart; -+ break; -+ default: -+ continue; -+ } -+ -+ /* verify that the SubAuthorityCount does not exceed the maximum permitted value */ -+ if (sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) -+ continue; -+ -+ n = sprintf( sidtxt, "S-%u-%d", sid->Revision, -+ MAKELONG( -+ MAKEWORD( sid->IdentifierAuthority.Value[5], -+ sid->IdentifierAuthority.Value[4] ), -+ MAKEWORD( sid->IdentifierAuthority.Value[3], -+ sid->IdentifierAuthority.Value[2] ) -+ ) ); -+ s = sidtxt + n; -+ for( j=0; jSubAuthorityCount; j++ ) -+ s += sprintf( s, "-%u", sid->SubAuthority[j] ); -+ -+ p += snprintf( p, XATTR_SIZE_MAX-(p-buffer), "%s%x,%x,%x,%s", -+ (p != buffer ? ";" : ""), type, flags, mask, sidtxt ); -+ } -+ -+ buffer[XATTR_SIZE_MAX-1] = 0; /* ensure NULL terminated if snprintf truncated the buffer */ -+ fsetxattr( fd, "user.wine.acl", buffer, p-buffer, 0 ); ++ /* include the descriptor revision and resource manager control bits */ ++ buffer[0] = SECURITY_DESCRIPTOR_REVISION; ++ buffer[1] = 0; ++ memcpy( &buffer[2], sd, len - 2 ); ++ fsetxattr( fd, "user.wine.sd", buffer, len, 0 ); +#endif +} + static struct object *create_file( struct fd *root, const char *nameptr, data_size_t len, unsigned int access, unsigned int sharing, int create, unsigned int options, unsigned int attrs, -@@ -239,6 +307,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si +@@ -239,6 +267,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si /* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */ fd = open_fd( root, name, flags | O_NONBLOCK | O_LARGEFILE, &mode, access, sharing, options ); if (!fd) goto done; -+ set_xattr_acls( get_unix_fd( fd ), sd ); ++ set_xattr_sd( get_unix_fd( fd ), sd ); if (S_ISDIR(mode)) obj = create_dir_obj( fd, access, mode ); -@@ -580,6 +649,8 @@ int file_set_acls( struct object *obj, struct fd *fd, const struct security_desc +@@ -580,6 +609,8 @@ int set_file_sd( struct object *obj, struct fd *fd, const struct security_descri mode = st.st_mode & (S_ISUID|S_ISGID|S_ISVTX); mode |= sd_to_mode( sd, owner ); -+ set_xattr_acls( unix_fd, sd ); ++ set_xattr_sd( unix_fd, sd ); + if (((st.st_mode ^ mode) & (S_IRWXU|S_IRWXG|S_IRWXO)) && fchmod( unix_fd, mode ) == -1) { diff --git a/patches/02-ACL_Extended_Attributes/0004-server-Retrieve-file-security-attributes-with-extend.patch b/patches/02-ACL_Extended_Attributes/0004-server-Retrieve-file-security-attributes-with-extend.patch index 61d43252..4e9e81bd 100644 --- a/patches/02-ACL_Extended_Attributes/0004-server-Retrieve-file-security-attributes-with-extend.patch +++ b/patches/02-ACL_Extended_Attributes/0004-server-Retrieve-file-security-attributes-with-extend.patch @@ -1,13 +1,13 @@ -From b08167fa305b8cee98df3b8712c01ebbc5f56dde Mon Sep 17 00:00:00 2001 +From 469fa2de7b5ea74c880a64c4acbb31a2397c8dc4 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" -Date: Tue, 15 Apr 2014 15:04:29 -0600 +Date: Thu, 17 Apr 2014 16:09:01 -0600 Subject: server: Retrieve file security attributes with extended file attributes. --- - dlls/advapi32/tests/security.c | 49 ++++++------ - server/file.c | 169 +++++++++++++++++++++++++++++++++++++++- - 2 files changed, 190 insertions(+), 28 deletions(-) + dlls/advapi32/tests/security.c | 49 ++++++++++++++-------------- + server/file.c | 70 ++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 91 insertions(+), 28 deletions(-) diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index bd45189..e5ef7e6 100644 @@ -110,167 +110,68 @@ index bd45189..e5ef7e6 100644 CloseHandle(obj); } diff --git a/server/file.c b/server/file.c -index 032205e..945b82a 100644 +index ceb57be..430d183 100644 --- a/server/file.c +++ b/server/file.c -@@ -493,12 +493,174 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID +@@ -453,12 +453,75 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID return sd; } -+struct security_descriptor *get_xattr_acls( int fd, const SID *user, const SID *group ) ++struct security_descriptor *get_xattr_sd( int fd, const SID *user, const SID *group ) +{ +#ifdef HAVE_ATTR_XATTR_H -+ int ace_count = 0, dacl_size = sizeof(ACL), i, n; -+ char buffer[XATTR_SIZE_MAX], *p = buffer, *pn; ++ char buffer[XATTR_SIZE_MAX], *sd_ptr, *buffer_ptr; + struct security_descriptor *sd; -+ ACE_HEADER *current_ace; -+ ACCESS_ALLOWED_ACE *aaa; -+ ACCESS_DENIED_ACE *ada; -+ int type, flags, mask; -+ ACL *dacl; -+ char *ptr; ++ int n, owner_len, group_len; + -+ n = fgetxattr( fd, "user.wine.acl", buffer, sizeof(buffer) ); ++ n = fgetxattr( fd, "user.wine.sd", buffer, sizeof(buffer) ); + if (n == -1) return NULL; -+ buffer[n] = 0; /* ensure NULL terminated buffer for string functions */ ++ /* validate that we can handle the descriptor */ ++ if (buffer[0] != SECURITY_DESCRIPTOR_REVISION || buffer[1] != 0) return NULL; + -+ do ++ owner_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]); ++ group_len = FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]); ++ sd = mem_alloc( n - 2 + owner_len + group_len ); ++ sd_ptr = (char *)sd; ++ buffer_ptr = &buffer[2]; ++ memcpy( sd_ptr, buffer_ptr, sizeof(struct security_descriptor)); ++ sd_ptr += sizeof(struct security_descriptor); ++ buffer_ptr += sizeof(struct security_descriptor); ++ ++ /* if no owner or group information is stored in the SD then return the corresponding data ++ * from the information stored in the filesystem */ ++ if (!sd->owner_len) + { -+ int sub_authority_count = 0; -+ -+ pn = strchr(p, ';'); -+ if (pn) pn++; -+ sscanf(p, "%x", &type); -+ do -+ { -+ p = strchr(p, '-'); -+ if (p) p++; -+ sub_authority_count++; -+ } -+ while(p && (!pn || p < pn)); -+ sub_authority_count -= 3; /* Revision and IdentifierAuthority don't count */ -+ p = pn; /* prepare for the next ACE */ -+ -+ /* verify that the SubAuthorityCount does not exceed the maximum permitted value */ -+ if (sub_authority_count > SID_MAX_SUB_AUTHORITIES) -+ continue; -+ -+ switch (type) -+ { -+ case ACCESS_DENIED_ACE_TYPE: -+ dacl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + -+ FIELD_OFFSET(SID, SubAuthority[sub_authority_count]); -+ break; -+ case ACCESS_ALLOWED_ACE_TYPE: -+ dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + -+ FIELD_OFFSET(SID, SubAuthority[sub_authority_count]); -+ break; -+ default: -+ continue; -+ } -+ ace_count++; ++ memcpy( sd_ptr, user, owner_len ); ++ sd_ptr += owner_len; + } -+ while(p); -+ -+ sd = mem_alloc( sizeof(struct security_descriptor) + -+ FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) + -+ FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]) + -+ dacl_size ); -+ -+ sd->control = SE_DACL_PRESENT; -+ sd->owner_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]); -+ sd->group_len = FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]); -+ sd->sacl_len = 0; -+ sd->dacl_len = dacl_size; -+ -+ ptr = (char *)(sd + 1); -+ memcpy( ptr, user, sd->owner_len ); -+ ptr += sd->owner_len; -+ memcpy( ptr, group, sd->group_len ); -+ ptr += sd->group_len; -+ -+ dacl = (ACL *)ptr; -+ dacl->AclRevision = ACL_REVISION; -+ dacl->Sbz1 = 0; -+ dacl->AclSize = dacl_size; -+ dacl->AceCount = ace_count; -+ dacl->Sbz2 = 0; -+ aaa = (ACCESS_ALLOWED_ACE *)(dacl + 1); -+ current_ace = &aaa->Header; -+ -+ p = buffer; -+ for(i=0; iHeader; -+ } -+ pn = strchr(p, ';'); -+ if (pn) pn++; -+ sscanf(p, "%x,%x,%x,%[^;]", &type, &flags, &mask, sidtxt); -+ sscanf(sidtxt, "S-%u-%d", &rev, &ia); -+ sid->Revision = rev; -+ sid->IdentifierAuthority.Value[0] = 0; -+ sid->IdentifierAuthority.Value[1] = 0; -+ sid->IdentifierAuthority.Value[2] = HIBYTE(HIWORD(ia)); -+ sid->IdentifierAuthority.Value[3] = LOBYTE(HIWORD(ia)); -+ sid->IdentifierAuthority.Value[4] = HIBYTE(LOWORD(ia)); -+ sid->IdentifierAuthority.Value[5] = LOBYTE(LOWORD(ia)); -+ p = strchr(sidtxt, '-')+1; -+ p = strchr(p, '-')+1; /* Revision doesn't count */ -+ p = strchr(p, '-')+1; /* IdentifierAuthority doesn't count */ -+ do -+ { -+ if (sub_authority_count == SID_MAX_SUB_AUTHORITIES) -+ { -+ sub_authority_count++; /* fail on this SID and move on to the next one */ -+ break; -+ } -+ sscanf(p, "%u", &sa); -+ sid->SubAuthority[sub_authority_count] = sa; -+ p = strchr(p, '-'); -+ if (p) p++; -+ sub_authority_count++; -+ } -+ while(p); -+ sid->SubAuthorityCount = sub_authority_count; -+ p = pn; /* prepare for the next ACE */ -+ -+ /* verify that the SubAuthorityCount does not exceed the maximum permitted value */ -+ if (sub_authority_count > SID_MAX_SUB_AUTHORITIES) -+ continue; -+ -+ /* Handle the specific ACE */ -+ switch (type) -+ { -+ case ACCESS_DENIED_ACE_TYPE: -+ ada = (ACCESS_DENIED_ACE *)aaa; -+ ada->Header.AceType = type; -+ ada->Header.AceFlags = flags; -+ ada->Header.AceSize = FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + -+ FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]); -+ ada->Mask = mask; -+ memcpy( &ada->SidStart, sid, FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]) ); -+ break; -+ case ACCESS_ALLOWED_ACE_TYPE: -+ aaa->Header.AceType = type; -+ aaa->Header.AceFlags = flags; -+ aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + -+ FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]); -+ aaa->Mask = mask; -+ memcpy( &aaa->SidStart, sid, FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]) ); -+ break; -+ default: -+ continue; -+ } ++ memcpy( sd_ptr, buffer_ptr, sd->owner_len ); ++ sd_ptr += sd->owner_len; + } ++ buffer_ptr += sd->owner_len; ++ if (!sd->owner_len) ++ { ++ memcpy( sd_ptr, group, group_len ); ++ sd_ptr += group_len; ++ } ++ else ++ { ++ memcpy( sd_ptr, buffer_ptr, sd->group_len ); ++ sd_ptr += sd->group_len; ++ } ++ buffer_ptr += sd->group_len; ++ ++ memcpy( sd_ptr, buffer_ptr, sd->sacl_len ); ++ sd_ptr += sd->sacl_len; ++ buffer_ptr += sd->sacl_len; ++ memcpy( sd_ptr, buffer_ptr, sd->dacl_len ); ++ sd_ptr += sd->dacl_len; ++ buffer_ptr += sd->dacl_len; ++ ++ sd->owner_len = owner_len; ++ sd->group_len = group_len; + + return sd; +#else @@ -278,8 +179,8 @@ index 032205e..945b82a 100644 +#endif +} + - struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mode_t *mode, - uid_t *uid ) + struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode_t *mode, + uid_t *uid ) { int unix_fd = get_unix_fd( fd ); struct stat st; @@ -288,7 +189,7 @@ index 032205e..945b82a 100644 if (unix_fd == -1 || fstat( unix_fd, &st ) == -1) return obj->sd; -@@ -508,9 +670,10 @@ struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mo +@@ -468,9 +531,10 @@ struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode (st.st_uid == *uid)) return obj->sd; @@ -297,7 +198,7 @@ index 032205e..945b82a 100644 - token_get_primary_group( current->process->token )); + user = security_unix_uid_to_sid( st.st_uid ); + group = token_get_primary_group( current->process->token ); -+ sd = get_xattr_acls( unix_fd, user, group ); ++ sd = get_xattr_sd( unix_fd, user, group ); + if (!sd) sd = mode_to_sd( st.st_mode, user, group); if (!sd) return obj->sd; diff --git a/patches/02-ACL_Extended_Attributes/0005-server-Convert-return-of-file-security-masks-with-ge.patch b/patches/02-ACL_Extended_Attributes/0005-server-Convert-return-of-file-security-masks-with-ge.patch index 2fb98ccd..80f1760f 100644 --- a/patches/02-ACL_Extended_Attributes/0005-server-Convert-return-of-file-security-masks-with-ge.patch +++ b/patches/02-ACL_Extended_Attributes/0005-server-Convert-return-of-file-security-masks-with-ge.patch @@ -1,6 +1,6 @@ -From e1b3d93adab31966d145ea41a9246d8f498c09d6 Mon Sep 17 00:00:00 2001 +From b4c7ea2450c3f02b761909812403c0b83ebb7e97 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" -Date: Thu, 13 Feb 2014 16:06:54 -0700 +Date: Thu, 17 Apr 2014 16:09:32 -0600 Subject: server: Convert return of file security masks with generic access mappings. @@ -10,7 +10,7 @@ Subject: server: Convert return of file security masks with generic access 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c -index f107abc..b71bad3 100644 +index e5ef7e6..5b7e6a6 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -3109,8 +3109,8 @@ static void test_CreateDirectoryA(void) @@ -80,10 +80,10 @@ index f107abc..b71bad3 100644 CloseHandle(obj); } diff --git a/server/file.c b/server/file.c -index b9135b9..0df2245 100644 +index 430d183..572b31f 100644 --- a/server/file.c +++ b/server/file.c -@@ -637,6 +637,27 @@ struct security_descriptor *get_xattr_acls( int fd, const SID *user, const SID * +@@ -515,6 +515,27 @@ struct security_descriptor *get_xattr_sd( int fd, const SID *user, const SID *gr #endif } @@ -108,13 +108,13 @@ index b9135b9..0df2245 100644 + } +} + - struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mode_t *mode, - uid_t *uid ) + struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode_t *mode, + uid_t *uid ) { -@@ -656,6 +677,7 @@ struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mo +@@ -534,6 +555,7 @@ struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode user = security_unix_uid_to_sid( st.st_uid ); group = token_get_primary_group( current->process->token ); - sd = get_xattr_acls( unix_fd, user, group ); + sd = get_xattr_sd( unix_fd, user, group ); + if (sd) convert_generic_sd( sd ); if (!sd) sd = mode_to_sd( st.st_mode, user, group); if (!sd) return obj->sd; diff --git a/patches/02-ACL_Extended_Attributes/0006-server-Inherit-security-attributes-from-parent-direc.patch b/patches/02-ACL_Extended_Attributes/0006-server-Inherit-security-attributes-from-parent-direc.patch index abecf0e3..fdb38cb1 100644 --- a/patches/02-ACL_Extended_Attributes/0006-server-Inherit-security-attributes-from-parent-direc.patch +++ b/patches/02-ACL_Extended_Attributes/0006-server-Inherit-security-attributes-from-parent-direc.patch @@ -1,6 +1,6 @@ -From 0c94a31c11260ec1ead91c47737d32cde97fee63 Mon Sep 17 00:00:00 2001 +From 657456dc0bb9846fb79ca5c3b3705b70fb13bfe1 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" -Date: Tue, 15 Apr 2014 15:19:52 -0600 +Date: Thu, 17 Apr 2014 16:10:07 -0600 Subject: server: Inherit security attributes from parent directories on creation. @@ -73,23 +73,23 @@ index 5b7e6a6..68b63a0 100644 HeapFree(GetProcessHeap(), 0, user); bret = RemoveDirectoryA(tmpdir); diff --git a/server/change.c b/server/change.c -index eb16923..1571eb8 100644 +index c391180..2cf1cab 100644 --- a/server/change.c +++ b/server/change.c @@ -287,7 +287,7 @@ static struct security_descriptor *dir_get_sd( struct object *obj ) assert( obj->ops == &dir_ops ); fd = dir_get_fd( obj ); -- sd = file_get_acls( obj, fd, &dir->mode, &dir->uid ); -+ sd = file_get_acls( obj, fd, &dir->mode, &dir->uid, TRUE ); +- sd = set_file_sd( obj, fd, &dir->mode, &dir->uid ); ++ sd = get_file_sd( obj, fd, &dir->mode, &dir->uid, TRUE ); release_object( fd ); return sd; } diff --git a/server/file.c b/server/file.c -index a12679d..eae4984 100644 +index 572b31f..0a29948 100644 --- a/server/file.c +++ b/server/file.c -@@ -246,11 +246,141 @@ void set_xattr_acls( int fd, const struct security_descriptor *sd ) +@@ -206,11 +206,141 @@ void set_xattr_sd( int fd, const struct security_descriptor *sd ) #endif } @@ -210,7 +210,7 @@ index a12679d..eae4984 100644 + fd = file_get_fd( obj ); + if (fd) + { -+ sd = file_get_acls( obj, fd, &file->mode, &file->uid, FALSE ); ++ sd = get_file_sd( obj, fd, &file->mode, &file->uid, FALSE ); + release_object( fd ); + } + if (sd) @@ -231,7 +231,7 @@ index a12679d..eae4984 100644 struct object *obj = NULL; struct fd *fd; int flags; -@@ -279,6 +409,10 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si +@@ -239,6 +369,10 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si default: set_error( STATUS_INVALID_PARAMETER ); goto done; } @@ -242,7 +242,7 @@ index a12679d..eae4984 100644 if (sd) { const SID *owner = sd_get_owner( sd ); -@@ -319,6 +453,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si +@@ -279,6 +413,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si release_object( fd ); done: @@ -250,43 +250,43 @@ index a12679d..eae4984 100644 free( name ); return obj; } -@@ -676,7 +811,7 @@ void convert_generic_sd( struct security_descriptor *sd ) +@@ -537,7 +672,7 @@ void convert_generic_sd( struct security_descriptor *sd ) } - struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mode_t *mode, -- uid_t *uid ) -+ uid_t *uid, int convert_generic ) + struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode_t *mode, +- uid_t *uid ) ++ uid_t *uid, int convert_generic ) { int unix_fd = get_unix_fd( fd ); struct stat st; -@@ -694,7 +829,7 @@ struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mo +@@ -555,7 +690,7 @@ struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode user = security_unix_uid_to_sid( st.st_uid ); group = token_get_primary_group( current->process->token ); - sd = get_xattr_acls( unix_fd, user, group ); + sd = get_xattr_sd( unix_fd, user, group ); - if (sd) convert_generic_sd( sd ); + if (sd && convert_generic) convert_generic_sd( sd ); if (!sd) sd = mode_to_sd( st.st_mode, user, group); if (!sd) return obj->sd; -@@ -714,7 +849,7 @@ static struct security_descriptor *file_get_sd( struct object *obj ) +@@ -575,7 +710,7 @@ static struct security_descriptor *file_get_sd( struct object *obj ) assert( obj->ops == &file_ops ); fd = file_get_fd( obj ); -- sd = file_get_acls( obj, fd, &file->mode, &file->uid ); -+ sd = file_get_acls( obj, fd, &file->mode, &file->uid, TRUE ); +- sd = get_file_sd( obj, fd, &file->mode, &file->uid ); ++ sd = get_file_sd( obj, fd, &file->mode, &file->uid, TRUE ); release_object( fd ); return sd; } diff --git a/server/file.h b/server/file.h -index 89b5888..0905fbb 100644 +index 43a234f..2f537cf 100644 --- a/server/file.h +++ b/server/file.h @@ -125,7 +125,7 @@ extern mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner - extern int file_set_acls( struct object *obj, struct fd *fd, const struct security_descriptor *sd, - unsigned int set_info ); - extern struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mode_t *mode, -- uid_t *uid ); -+ uid_t *uid, int convert_generic ); + extern int set_file_sd( struct object *obj, struct fd *fd, 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 ); ++ uid_t *uid, int convert_generic ); /* file mapping functions */ diff --git a/patches/02-ACL_Extended_Attributes/0007-server-Inherit-security-attributes-from-parent-direc.patch b/patches/02-ACL_Extended_Attributes/0007-server-Inherit-security-attributes-from-parent-direc.patch index a05ce550..f3cbabf7 100644 --- a/patches/02-ACL_Extended_Attributes/0007-server-Inherit-security-attributes-from-parent-direc.patch +++ b/patches/02-ACL_Extended_Attributes/0007-server-Inherit-security-attributes-from-parent-direc.patch @@ -1,6 +1,6 @@ -From c71273c87839889d351fe8c5b84f3c947783500a Mon Sep 17 00:00:00 2001 +From cefa61c21ee6aacaff75f9c98c779a362a01845d Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" -Date: Tue, 15 Apr 2014 15:23:46 -0600 +Date: Thu, 17 Apr 2014 16:10:17 -0600 Subject: server: Inherit security attributes from parent directories on SetSecurityInfo. @@ -146,10 +146,10 @@ index fa8874c..9e6b9a8 100644 if (orig->inode) diff --git a/server/file.c b/server/file.c -index eae4984..08d2db0 100644 +index 0a29948..fe0b88f 100644 --- a/server/file.c +++ b/server/file.c -@@ -326,6 +326,105 @@ struct security_descriptor *inherit_sd( const struct security_descriptor *parent +@@ -286,6 +286,105 @@ struct security_descriptor *inherit_sd( const struct security_descriptor *parent return sd; } @@ -255,13 +255,13 @@ index eae4984..08d2db0 100644 static struct security_descriptor *file_get_parent_sd( struct fd *root, const char *child_name, int child_len, int is_dir ) { -@@ -933,16 +1032,33 @@ mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner ) +@@ -794,16 +893,33 @@ mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner ) return new_mode & ~denied_mode; } --int file_set_acls( struct object *obj, struct fd *fd, const struct security_descriptor *sd, -+int file_set_acls( struct object *obj, struct fd *fd, const struct security_descriptor *new_sd, - unsigned int set_info ) +-int set_file_sd( struct object *obj, struct fd *fd, const struct security_descriptor *sd, ++int set_file_sd( struct object *obj, struct fd *fd, const struct security_descriptor *new_sd, + unsigned int set_info ) { + const struct security_descriptor *sd = new_sd; + struct security_descriptor *parent_sd = NULL; @@ -290,7 +290,7 @@ index eae4984..08d2db0 100644 if (set_info & OWNER_SECURITY_INFORMATION) { owner = sd_get_owner( sd ); -@@ -974,10 +1090,14 @@ int file_set_acls( struct object *obj, struct fd *fd, const struct security_desc +@@ -835,10 +951,14 @@ int set_file_sd( struct object *obj, struct fd *fd, const struct security_descri if (((st.st_mode ^ mode) & (S_IRWXU|S_IRWXG|S_IRWXO)) && fchmod( unix_fd, mode ) == -1) { file_set_error(); @@ -308,7 +308,7 @@ index eae4984..08d2db0 100644 static int file_set_sd( struct object *obj, const struct security_descriptor *sd, diff --git a/server/file.h b/server/file.h -index 0905fbb..8cbc4cb 100644 +index 2f537cf..fa83001 100644 --- a/server/file.h +++ b/server/file.h @@ -77,6 +77,7 @@ extern void allow_fd_caching( struct fd *fd ); diff --git a/patches/02-ACL_Extended_Attributes/0009-server-Add-compatibility-code-for-handling-the-old-m.patch b/patches/02-ACL_Extended_Attributes/0009-server-Add-compatibility-code-for-handling-the-old-m.patch new file mode 100644 index 00000000..31f1d156 --- /dev/null +++ b/patches/02-ACL_Extended_Attributes/0009-server-Add-compatibility-code-for-handling-the-old-m.patch @@ -0,0 +1,193 @@ +From 2e2b2120c5b4930ec89aaf074c1c78e0dd61bc59 Mon Sep 17 00:00:00 2001 +From: "Erich E. Hoover" +Date: Thu, 17 Apr 2014 16:11:25 -0600 +Subject: server: Add compatibility code for handling the old method of + storing ACLs. + +--- + server/file.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 162 insertions(+) + +diff --git a/server/file.c b/server/file.c +index fe0b88f..ea31a29 100644 +--- a/server/file.c ++++ b/server/file.c +@@ -687,6 +687,167 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID + return sd; + } + ++struct security_descriptor *get_xattr_acls( int fd, const SID *user, const SID *group ) ++{ ++#ifdef HAVE_ATTR_XATTR_H ++ int ace_count = 0, dacl_size = sizeof(ACL), i, n; ++ char buffer[XATTR_SIZE_MAX], *p = buffer, *pn; ++ struct security_descriptor *sd; ++ ACE_HEADER *current_ace; ++ ACCESS_ALLOWED_ACE *aaa; ++ ACCESS_DENIED_ACE *ada; ++ int type, flags, mask; ++ ACL *dacl; ++ char *ptr; ++ ++ n = fgetxattr( fd, "user.wine.acl", buffer, sizeof(buffer) ); ++ if (n == -1) return NULL; ++ buffer[n] = 0; /* ensure NULL terminated buffer for string functions */ ++ ++ do ++ { ++ int sub_authority_count = 0; ++ ++ pn = strchr(p, ';'); ++ if (pn) pn++; ++ sscanf(p, "%x", &type); ++ do ++ { ++ p = strchr(p, '-'); ++ if (p) p++; ++ sub_authority_count++; ++ } ++ while(p && (!pn || p < pn)); ++ sub_authority_count -= 3; /* Revision and IdentifierAuthority don't count */ ++ p = pn; /* prepare for the next ACE */ ++ ++ /* verify that the SubAuthorityCount does not exceed the maximum permitted value */ ++ if (sub_authority_count > SID_MAX_SUB_AUTHORITIES) ++ continue; ++ ++ switch (type) ++ { ++ case ACCESS_DENIED_ACE_TYPE: ++ dacl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + ++ FIELD_OFFSET(SID, SubAuthority[sub_authority_count]); ++ break; ++ case ACCESS_ALLOWED_ACE_TYPE: ++ dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + ++ FIELD_OFFSET(SID, SubAuthority[sub_authority_count]); ++ break; ++ default: ++ continue; ++ } ++ ace_count++; ++ } ++ while(p); ++ ++ sd = mem_alloc( sizeof(struct security_descriptor) + ++ FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) + ++ FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]) + ++ dacl_size ); ++ ++ sd->control = SE_DACL_PRESENT; ++ sd->owner_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]); ++ sd->group_len = FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]); ++ sd->sacl_len = 0; ++ sd->dacl_len = dacl_size; ++ ++ ptr = (char *)(sd + 1); ++ memcpy( ptr, user, sd->owner_len ); ++ ptr += sd->owner_len; ++ memcpy( ptr, group, sd->group_len ); ++ ptr += sd->group_len; ++ ++ dacl = (ACL *)ptr; ++ dacl->AclRevision = ACL_REVISION; ++ dacl->Sbz1 = 0; ++ dacl->AclSize = dacl_size; ++ dacl->AceCount = ace_count; ++ dacl->Sbz2 = 0; ++ aaa = (ACCESS_ALLOWED_ACE *)(dacl + 1); ++ current_ace = &aaa->Header; ++ ++ p = buffer; ++ for(i=0; iHeader; ++ } ++ pn = strchr(p, ';'); ++ if (pn) pn++; ++ sscanf(p, "%x,%x,%x,%[^;]", &type, &flags, &mask, sidtxt); ++ sscanf(sidtxt, "S-%u-%d", &rev, &ia); ++ sid->Revision = rev; ++ sid->IdentifierAuthority.Value[0] = 0; ++ sid->IdentifierAuthority.Value[1] = 0; ++ sid->IdentifierAuthority.Value[2] = HIBYTE(HIWORD(ia)); ++ sid->IdentifierAuthority.Value[3] = LOBYTE(HIWORD(ia)); ++ sid->IdentifierAuthority.Value[4] = HIBYTE(LOWORD(ia)); ++ sid->IdentifierAuthority.Value[5] = LOBYTE(LOWORD(ia)); ++ p = strchr(sidtxt, '-')+1; ++ p = strchr(p, '-')+1; /* Revision doesn't count */ ++ p = strchr(p, '-')+1; /* IdentifierAuthority doesn't count */ ++ do ++ { ++ if (sub_authority_count == SID_MAX_SUB_AUTHORITIES) ++ { ++ sub_authority_count++; /* fail on this SID and move on to the next one */ ++ break; ++ } ++ sscanf(p, "%u", &sa); ++ sid->SubAuthority[sub_authority_count] = sa; ++ p = strchr(p, '-'); ++ if (p) p++; ++ sub_authority_count++; ++ } ++ while(p); ++ sid->SubAuthorityCount = sub_authority_count; ++ p = pn; /* prepare for the next ACE */ ++ ++ /* verify that the SubAuthorityCount does not exceed the maximum permitted value */ ++ if (sub_authority_count > SID_MAX_SUB_AUTHORITIES) ++ continue; ++ ++ /* Handle the specific ACE */ ++ switch (type) ++ { ++ case ACCESS_DENIED_ACE_TYPE: ++ ada = (ACCESS_DENIED_ACE *)aaa; ++ ada->Header.AceType = type; ++ ada->Header.AceFlags = flags; ++ ada->Header.AceSize = FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + ++ FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]); ++ ada->Mask = mask; ++ memcpy( &ada->SidStart, sid, FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]) ); ++ break; ++ case ACCESS_ALLOWED_ACE_TYPE: ++ aaa->Header.AceType = type; ++ aaa->Header.AceFlags = flags; ++ aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + ++ FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]); ++ aaa->Mask = mask; ++ memcpy( &aaa->SidStart, sid, FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]) ); ++ break; ++ default: ++ continue; ++ } ++ } ++ ++ return sd; ++#else ++ return NULL; ++#endif ++} ++ + struct security_descriptor *get_xattr_sd( int fd, const SID *user, const SID *group ) + { + #ifdef HAVE_ATTR_XATTR_H +@@ -789,6 +950,7 @@ struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode + user = security_unix_uid_to_sid( st.st_uid ); + group = token_get_primary_group( current->process->token ); + sd = get_xattr_sd( unix_fd, user, group ); ++ if (!sd) sd = get_xattr_acls( unix_fd, user, group ); + if (sd && convert_generic) convert_generic_sd( sd ); + if (!sd) sd = mode_to_sd( st.st_mode, user, group); + if (!sd) return obj->sd; +-- +1.7.9.5 + diff --git a/patches/02-ACL_Extended_Attributes/92938b89-506b-430a-ba50-32de8b286e56.def b/patches/02-ACL_Extended_Attributes/92938b89-506b-430a-ba50-32de8b286e56.def index a3a0a372..5adc79be 100644 --- a/patches/02-ACL_Extended_Attributes/92938b89-506b-430a-ba50-32de8b286e56.def +++ b/patches/02-ACL_Extended_Attributes/92938b89-506b-430a-ba50-32de8b286e56.def @@ -1,3 +1,3 @@ -Revision: 2 +Revision: 3 Author: Erich E. Hoover Title: Store and return security attributes with extended file attributes. diff --git a/patches/patch-list.patch b/patches/patch-list.patch index 3b78942f..93d54ac7 100644 --- a/patches/patch-list.patch +++ b/patches/patch-list.patch @@ -47,7 +47,7 @@ index a273502..5fa0cd5 100644 + const char *title; +} wine_patch_data[] = { + { "8a366b6d-8ad6-4581-8aa9-66a03590a57b:2", "Erich E. Hoover", "Implement SIO_ADDRESS_LIST_CHANGE." }, -+ { "92938b89-506b-430a-ba50-32de8b286e56:2", "Erich E. Hoover", "Store and return security attributes with extended file attributes." }, ++ { "92938b89-506b-430a-ba50-32de8b286e56:3", "Erich E. Hoover", "Store and return security attributes with extended file attributes." }, + { "5d6bb7b5-ec88-4ed3-907d-9ad2173a2f88:1", "Sebastian Lackner", "Enable/disable windows when they are (un)mapped by foreign applications." }, + { "94186fff-6dbf-44d0-8eb1-2463d1608a0f:1", "Sebastian Lackner", "Update gl_drawable for embedded windows." }, + { "cbe240e8-2c58-430a-b61c-7fbb9d0e1e11:1", "Sebastian Lackner", "Change return value of stub SetNamedPipeHandleState to TRUE." },