- From eeb509f0d0e8fe9d2f17ee16beeb12ae59570d88 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Sat, 20 Apr 2024 13:23:54 +0200
- Subject: [PATCH 1/5] sys: Undo #8f4ae667b1800205319a4518876eb7ec170d9390,
- |entry->filename| is required
- Backout commit #8f4ae667b1800205319a4518876eb7ec170d9390 ("sys: Remove
- |MmIsAddressValid()| from hot codepath"), it seems that under high load
- |entry->filename| and/or |entry->filename->Buffer| can contain garbage.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- sys/nfs41_driver.c | 16 +++++++++-------
- 1 file changed, 9 insertions(+), 7 deletions(-)
- diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c
- index 535320e..f1135ad 100644
- --- a/sys/nfs41_driver.c
- +++ b/sys/nfs41_driver.c
- @@ -45,7 +45,6 @@
- /* debugging printout defines */
- #define DEBUG_MARSHAL_HEADER
- -//#define DEBUG_MARSHAL_HEADER_VALID_FILENAME
- #define DEBUG_MARSHAL_DETAIL
- //#define DEBUG_OPEN
- //#define DEBUG_CLOSE
- @@ -602,21 +601,24 @@ NTSTATUS marshal_nfs41_header(
- RtlCopyMemory(tmp, &entry->open_state, sizeof(HANDLE));
- tmp += sizeof(HANDLE);
- + /*
- + * gisburn: FIXME: For currently unknown reasons we need to
- + * validate |entry->filename|+it's contents, because a heavily
- + * stressed system somehow sometimes causes garbage there
- + */
- + if (MmIsAddressValid(entry->filename) &&
- + (entry->filename != NULL) &&
- + MmIsAddressValid(entry->filename->Buffer))
- #ifdef DEBUG_MARSHAL_HEADER
- -#ifdef DEBUG_MARSHAL_HEADER_VALID_FILENAME
- - if (MmIsAddressValid(entry->filename))
- -#endif
- DbgP("[upcall header] xid=%lld opcode='%s' filename='%wZ' version=%d "
- "session=0x%x open_state=0x%x\n", entry->xid,
- ENTRY_OPCODE2STRING(entry), entry->filename,
- entry->version, entry->session, entry->open_state);
- -#ifdef DEBUG_MARSHAL_HEADER_VALID_FILENAME
- +#endif /* DEBUG_MARSHAL_HEADER */
- else {
- DbgP("[upcall header] Invalid filename %p\n", entry);
- status = STATUS_INTERNAL_ERROR;
- }
- -#endif /* DEBUG_MARSHAL_HEADER_VALID_FILENAME */
- -#endif /* DEBUG_MARSHAL_HEADER */
- out:
- return status;
- }
- --
- 2.43.0
- From 253743803499663bd01d583d829d5fc0dd47ee3a Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Mon, 22 Apr 2024 12:16:29 +0200
- Subject: [PATCH 2/5] daemon: Provide utility functions to get
- |TOKEN_USER|/|TOKEN_PRIMARY_GROUP|
- Provide utility functions |get_token_user_name()|+
- |get_token_primarygroup_name()| to get |TOKEN_USER|+
- |TOKEN_PRIMARY_GROUP| from a given token.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/util.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++
- daemon/util.h | 4 +++
- 2 files changed, 85 insertions(+)
- diff --git a/daemon/util.c b/daemon/util.c
- index 741a653..1ea5cfd 100644
- --- a/daemon/util.c
- +++ b/daemon/util.c
- @@ -25,6 +25,7 @@
- #include <stdio.h>
- #include <stdlib.h>
- #include <wincrypt.h> /* for Crypt*() functions */
- +#include <Lmcons.h>
- #include "daemon_debug.h"
- #include "util.h"
- @@ -717,3 +718,83 @@ bool getwinntversionnnumbers(
- return true;
- }
- +
- +/*
- + * Performance hack:
- + * GETTOKINFO_EXTRA_BUFFER - extra space for more data
- + * |GetTokenInformation()| for |TOKEN_USER| and |TOKEN_PRIMARY_GROUP|
- + * always fails in Win10 with |ERROR_INSUFFICIENT_BUFFER| if you
- + * just pass the |sizeof(TOKEN_*)| value. Instead of calling
- + * |GetTokenInformation()| with |NULL| arg to obtain the size to
- + * allocate we just provide 2048 bytes of extra space after the
- + * |TOKEN_*| size, and pray it is enough
- + */
- +#define GETTOKINFO_EXTRA_BUFFER (2048)
- +
- +bool get_token_user_name(HANDLE tok, char *out_buffer)
- +{
- + DWORD tokdatalen;
- + PTOKEN_USER ptuser;
- + PSID pusid;
- + DWORD namesize = UNLEN+1;
- + char domainbuffer[UNLEN+1];
- + DWORD domainbuffer_size = sizeof(domainbuffer);
- + SID_NAME_USE name_use;
- +
- + tokdatalen = sizeof(TOKEN_USER)+GETTOKINFO_EXTRA_BUFFER;
- + ptuser = _alloca(tokdatalen);
- + if (!GetTokenInformation(tok, TokenUser, ptuser,
- + tokdatalen, &tokdatalen)) {
- + eprintf("get_token_username: "
- + "GetTokenInformation(tok=0x%p, TokenUser) failed, "
- + "status=%d\n",
- + (void *)tok, (int)GetLastError());
- + return false;
- + }
- +
- + pusid = ptuser->User.Sid;
- +
- + if (!LookupAccountSidA(NULL, pusid, out_buffer, &namesize,
- + domainbuffer, &domainbuffer_size, &name_use)) {
- + eprintf("get_token_user_name: "
- + "LookupAccountSidA() failed, status=%d\n",
- + (int)GetLastError());
- + return false;
- + }
- +
- + return true;
- +}
- +
- +bool get_token_primarygroup_name(HANDLE tok, char *out_buffer)
- +{
- + DWORD tokdatalen;
- + PTOKEN_PRIMARY_GROUP ptpgroup;
- + PSID pgsid;
- + DWORD namesize = GNLEN+1;
- + char domainbuffer[UNLEN+1];
- + DWORD domainbuffer_size = sizeof(domainbuffer);
- + SID_NAME_USE name_use;
- +
- + tokdatalen = sizeof(TOKEN_PRIMARY_GROUP)+GETTOKINFO_EXTRA_BUFFER;
- + ptpgroup = _alloca(tokdatalen);
- + if (!GetTokenInformation(tok, TokenPrimaryGroup, ptpgroup,
- + tokdatalen, &tokdatalen)) {
- + eprintf("get_token_primarygroup_name: "
- + "GetTokenInformation(tok=0x%p, TokenPrimaryGroup) failed, "
- + "status=%d\n",
- + (void *)tok, (int)GetLastError());
- + return false;
- + }
- +
- + pgsid = ptpgroup->PrimaryGroup;
- +
- + if (!LookupAccountSidA(NULL, pgsid, out_buffer, &namesize,
- + domainbuffer, &domainbuffer_size, &name_use)) {
- + eprintf("get_token_username: "
- + "LookupAccountSidA() failed, status=%d\n",
- + (int)GetLastError());
- + return false;
- + }
- +
- + return true;
- +}
- diff --git a/daemon/util.h b/daemon/util.h
- index b1bdc8a..a09df70 100644
- --- a/daemon/util.h
- +++ b/daemon/util.h
- @@ -284,4 +284,8 @@ bool_t waitcriticalsection(LPCRITICAL_SECTION cs);
- bool getwinntversionnnumbers(DWORD *MajorVersionPtr, DWORD *MinorVersionPtr, DWORD *BuildNumberPtr);
- +bool get_token_user_name(HANDLE tok, char *out_buffer);
- +bool get_token_primarygroup_name(HANDLE tok, char *out_buffer);
- +
- +
- #endif /* !__NFS41_DAEMON_UTIL_H__ */
- --
- 2.43.0
- From 51495ba84760d908224e4233ce50b672ff493e4e Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Mon, 22 Apr 2024 12:20:00 +0200
- Subject: [PATCH 3/5] daemon: |logprintf()| should print current impersonated
- user+primary group
- |logprintf()| should print current impersonated user+primary group
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/daemon_debug.c | 13 +++++++++----
- 1 file changed, 9 insertions(+), 4 deletions(-)
- diff --git a/daemon/daemon_debug.c b/daemon/daemon_debug.c
- index 83f8612..b35bfee 100644
- --- a/daemon/daemon_debug.c
- +++ b/daemon/daemon_debug.c
- @@ -89,23 +89,28 @@ void logprintf(LPCSTR format, ...)
- {
- SYSTEMTIME stime;
- char username[UNLEN+1];
- - DWORD username_len = sizeof(username);
- + char groupname[GNLEN+1];
- GetLocalTime(&stime);
- - if (!GetUserNameA(username, &username_len)) {
- + if (!get_token_user_name(GetCurrentThreadEffectiveToken(),
- + username)) {
- (void)strcpy(username, "<unknown>");
- }
- + if (!get_token_primarygroup_name(GetCurrentThreadEffectiveToken(),
- + groupname)) {
- + (void)strcpy(groupname, "<unknown>");
- + }
- va_list args;
- va_start(args, format);
- (void)fprintf(dlog_file,
- "# LOG: ts=%04d-%02d-%02d_%02d:%02d:%02d:%04d"
- - " thr=%04x user='%s' msg=",
- + " thr=%04x user='%s'/'%s' msg=",
- (int)stime.wYear, (int)stime.wMonth, (int)stime.wDay,
- (int)stime.wHour, (int)stime.wMinute, (int)stime.wSecond,
- (int)stime.wMilliseconds,
- (int)GetCurrentThreadId(),
- - username);
- + username, groupname);
- (void)vfprintf(dlog_file, format, args);
- (void)fflush(dlog_file);
- va_end(args);
- --
- 2.43.0
- From 1081abedf16f90ed015ec96d13b0020036f76e7e Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Mon, 22 Apr 2024 16:14:32 +0200
- Subject: [PATCH 4/5] daemon: |nfs41_client_owner()| should use faster
- |get_token_user_name()|
- |nfs41_client_owner()| should use faster |get_token_user_name()|
- instead of |GetUserNameA()|
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/nfs41_client.c | 14 +++++++++-----
- 1 file changed, 9 insertions(+), 5 deletions(-)
- diff --git a/daemon/nfs41_client.c b/daemon/nfs41_client.c
- index d0306a0..2707414 100644
- --- a/daemon/nfs41_client.c
- +++ b/daemon/nfs41_client.c
- @@ -368,12 +368,16 @@ int nfs41_client_owner(
- DWORD length;
- const ULONGLONG time_created = GetTickCount64();
- int status;
- - char username[UNLEN + 1];
- - DWORD len = UNLEN + 1;
- -
- - if (!GetUserNameA(username, &len)) {
- + char username[UNLEN+1];
- +
- + /*
- + * gisburn: What about primary group (for /usr/bin/newgrp
- + * support) ?
- + */
- + if (!get_token_user_name(GetCurrentThreadEffectiveToken(),
- + username)) {
- status = GetLastError();
- - eprintf("GetUserName() failed with %d\n", status);
- + eprintf("get_token_user_name() failed with %d\n", status);
- goto out;
- }
- --
- 2.43.0
- From 0c83631ecc377864c2aca0d1a4c9a5bd7bfb230b Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Mon, 22 Apr 2024 16:24:21 +0200
- Subject: [PATCH 5/5] daemon,sys: Add experimental support for
- |setgid()|/newgrp(1)
- Add experimental support for |setgid()|/newgrp(1).
- This is currently implemented as a hack via setatttr to change the
- owner_group of newly created files.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/nfs41_daemon.c | 54 +++++++++++++++++++++++++++++++++++-------
- daemon/open.c | 23 ++++++++++++++++++
- nfs41_build_features.h | 6 +++++
- sys/nfs41_driver.c | 8 +++++++
- 4 files changed, 82 insertions(+), 9 deletions(-)
- diff --git a/daemon/nfs41_daemon.c b/daemon/nfs41_daemon.c
- index 5a6bbc2..c7bef5f 100644
- --- a/daemon/nfs41_daemon.c
- +++ b/daemon/nfs41_daemon.c
- @@ -67,25 +67,59 @@ typedef struct _nfs41_process_thread {
- uint32_t tid;
- } nfs41_process_thread;
- -static int map_current_user_to_ids(nfs41_idmapper *idmapper, uid_t *uid, gid_t *gid)
- +static int map_current_user_to_ids(nfs41_idmapper *idmapper, uid_t *puid, gid_t *pgid)
- {
- - char username[UNLEN + 1];
- - DWORD len = UNLEN + 1;
- + char username[UNLEN+1];
- + char pgroupname[GNLEN+1];
- int status = NO_ERROR;
- + HANDLE impersonation_tok = GetCurrentThreadEffectiveToken();
- + gid_t dummygid;
- - if (!GetUserNameA(username, &len)) {
- + if (!get_token_user_name(impersonation_tok, username)) {
- status = GetLastError();
- - eprintf("map_current_user_to_ids: GetUserName() failed with %d\n", status);
- + eprintf("map_current_user_to_ids: "
- + "get_token_user_name() failed with %d\n", status);
- goto out;
- }
- - DPRINTF(1, ("map_current_user_to_ids: mapping user '%s'\n", username));
- - if (nfs41_idmap_name_to_ids(idmapper, username, uid, gid)) {
- + if (!get_token_primarygroup_name(impersonation_tok, pgroupname)) {
- + status = GetLastError();
- + eprintf("map_current_user_to_ids: "
- + "get_token_primarygroup_name() failed with %d\n", status);
- + goto out;
- + }
- +
- + if (nfs41_idmap_name_to_ids(idmapper, username, puid, &dummygid)) {
- /* instead of failing for auth_sys, fall back to 'nobody' uid/gid */
- - *uid = nfs41_dg.default_uid;
- - *gid = nfs41_dg.default_gid;
- + DPRINTF(1,
- + ("map_current_user_to_ids: "
- + "nfs41_idmap_name_to_ids(username='%s') failed, "
- + "returning nobody/nogroup defaults\n",
- + username));
- + *puid = nfs41_dg.default_uid;
- + *pgid = nfs41_dg.default_gid;
- + status = NO_ERROR;
- + goto out;
- }
- +
- + if (nfs41_idmap_group_to_gid(
- + idmapper,
- + pgroupname,
- + pgid)) {
- + DPRINTF(1,
- + ("map_current_user_to_ids: "
- + "nfs41_idmap_group_to_gid(pgroupname='%s') failed, "
- + "returning nogroup\n",
- + pgroupname));
- + *pgid = nfs41_dg.default_gid;
- + }
- +
- out:
- + DPRINTF(1,
- + ("map_current_user_to_ids: "
- + "mapping user=(name='%s' ==> uid=%d)/pgroup=(name='%s' ==> gid=%d)\n",
- + username, (int)*puid,
- + pgroupname, (int)*pgid));
- return status;
- }
- @@ -649,6 +683,8 @@ VOID ServiceStart(DWORD argc, LPTSTR *argv)
- DPRINTF(0, ("SID cache disabled\n"));
- #endif /* NFS41_DRIVER_SID_CACHE */
- + logprintf("NFS client daemon starting...\n");
- +
- /* acquire and store in global memory current dns domain name.
- * needed for acls */
- if (getdomainname()) {
- diff --git a/daemon/open.c b/daemon/open.c
- index 85f0bcc..814354f 100644
- --- a/daemon/open.c
- +++ b/daemon/open.c
- @@ -941,6 +941,29 @@ supersede_retry:
- status = nfs_to_windows_error(status, ERROR_FILE_NOT_FOUND);
- goto out_free_state;
- } else {
- +#ifdef NFS41_DRIVER_SETGID_NEWGRP_SUPPORT
- + /*
- + * Hack: Support |setgid()|/newgrp(1) by fetching group
- + * name from auth token for new files and do a "manual"
- + * chgrp on the new file
- + */
- + if (create == OPEN4_CREATE) {
- + nfs41_file_info createchgrpattrs = { 0 };
- + createchgrpattrs.attrmask.count = 2;
- + createchgrpattrs.attrmask.arr[1] |= FATTR4_WORD1_OWNER_GROUP;
- + createchgrpattrs.owner_group = createchgrpattrs.owner_group_buf;
- + (void)get_token_primarygroup_name(GetCurrentThreadEffectiveToken(),
- + createchgrpattrs.owner_group);
- + (void)strcat(createchgrpattrs.owner_group, "@");
- + (void)strcat(createchgrpattrs.owner_group, nfs41dg->localdomain_name);
- + DPRINTF(1, ("handle_open(): create(), groupname='%s'\n", createchgrpattrs.owner_group));
- +
- + stateid_arg stateid;
- + nfs41_open_stateid_arg(state, &stateid);
- + (void)nfs41_setattr(state->session, &state->file, &stateid, &createchgrpattrs);
- + }
- +#endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
- +
- nfs_to_basic_info(state->file.name.name, &info, &args->basic_info);
- nfs_to_standard_info(&info, &args->std_info);
- args->mode = info.mode;
- diff --git a/nfs41_build_features.h b/nfs41_build_features.h
- index 2e18150..7b607ea 100644
- --- a/nfs41_build_features.h
- +++ b/nfs41_build_features.h
- @@ -93,4 +93,10 @@
- */
- #define NFS41_DRIVER_USE_LARGE_SOCKET_RCVSND_BUFFERS 1
- +/*
- + * Support /usr/bin/newgrp&co, which have a non-default
- + * |TOKEN_PRIMARY_GROUP|
- + */
- +#define NFS41_DRIVER_SETGID_NEWGRP_SUPPORT 1
- +
- #endif /* !_NFS41_DRIVER_BUILDFEATURES_ */
- diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c
- index f1135ad..b223d32 100644
- --- a/sys/nfs41_driver.c
- +++ b/sys/nfs41_driver.c
- @@ -41,7 +41,15 @@
- #include "nfs41_build_features.h"
- +/*
- + * FIXME: NFS41_DRIVER_SETGID_NEWGRP_SUPPORT - we need the correct
- + * |TOKEN_PRIMARY_GROUP| for |setgid()|/newgrp(1)
- + * support, and |#define USE_MOUNT_SEC_CONTEXT| currently breaks
- + * that
- + */
- +#ifndef NFS41_DRIVER_SETGID_NEWGRP_SUPPORT
- #define USE_MOUNT_SEC_CONTEXT
- +#endif
- /* debugging printout defines */
- #define DEBUG_MARSHAL_HEADER
- --
- 2.43.0
msnfs41client: Patch for |setgid()|/newgrp(1) support+misc, 2024-04-22
Posted by Anonymous on Mon 22nd Apr 2024 15:35
raw | new post
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.