pastebin - collaborative debugging tool
rovema.kpaste.net RSS


msnfs41client: Patch for |setgid()|/newgrp(1) support+misc, 2024-04-22
Posted by Anonymous on Mon 22nd Apr 2024 15:35
raw | new post

  1. From eeb509f0d0e8fe9d2f17ee16beeb12ae59570d88 Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Sat, 20 Apr 2024 13:23:54 +0200
  4. Subject: [PATCH 1/5] sys: Undo #8f4ae667b1800205319a4518876eb7ec170d9390,
  5.  |entry->filename| is required
  6.  
  7. Backout commit #8f4ae667b1800205319a4518876eb7ec170d9390 ("sys: Remove
  8. |MmIsAddressValid()| from hot codepath"), it seems that under high load
  9. |entry->filename| and/or |entry->filename->Buffer| can contain garbage.
  10.  
  11. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  12. ---
  13. sys/nfs41_driver.c | 16 +++++++++-------
  14.  1 file changed, 9 insertions(+), 7 deletions(-)
  15.  
  16. diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c
  17. index 535320e..f1135ad 100644
  18. --- a/sys/nfs41_driver.c
  19. +++ b/sys/nfs41_driver.c
  20. @@ -45,7 +45,6 @@
  21.  
  22.  /* debugging printout defines */
  23.  #define DEBUG_MARSHAL_HEADER
  24. -//#define DEBUG_MARSHAL_HEADER_VALID_FILENAME
  25.  #define DEBUG_MARSHAL_DETAIL
  26.  //#define DEBUG_OPEN
  27.  //#define DEBUG_CLOSE
  28. @@ -602,21 +601,24 @@ NTSTATUS marshal_nfs41_header(
  29.      RtlCopyMemory(tmp, &entry->open_state, sizeof(HANDLE));
  30.      tmp += sizeof(HANDLE);
  31.  
  32. +    /*
  33. +     * gisburn: FIXME: For currently unknown reasons we need to
  34. +     * validate |entry->filename|+it's contents, because a heavily
  35. +     * stressed system somehow sometimes causes garbage there
  36. +     */
  37. +    if (MmIsAddressValid(entry->filename) &&
  38. +        (entry->filename != NULL) &&
  39. +        MmIsAddressValid(entry->filename->Buffer))
  40.  #ifdef DEBUG_MARSHAL_HEADER
  41. -#ifdef DEBUG_MARSHAL_HEADER_VALID_FILENAME
  42. -    if (MmIsAddressValid(entry->filename))
  43. -#endif
  44.          DbgP("[upcall header] xid=%lld opcode='%s' filename='%wZ' version=%d "
  45.              "session=0x%x open_state=0x%x\n", entry->xid,
  46.              ENTRY_OPCODE2STRING(entry), entry->filename,
  47.              entry->version, entry->session, entry->open_state);
  48. -#ifdef DEBUG_MARSHAL_HEADER_VALID_FILENAME
  49. +#endif /* DEBUG_MARSHAL_HEADER */
  50.      else {
  51.          DbgP("[upcall header] Invalid filename %p\n", entry);
  52.          status = STATUS_INTERNAL_ERROR;
  53.      }
  54. -#endif /* DEBUG_MARSHAL_HEADER_VALID_FILENAME */
  55. -#endif /* DEBUG_MARSHAL_HEADER */
  56.  out:
  57.      return status;
  58.  }
  59. --
  60. 2.43.0
  61.  
  62. From 253743803499663bd01d583d829d5fc0dd47ee3a Mon Sep 17 00:00:00 2001
  63. From: Roland Mainz <roland.mainz@nrubsig.org>
  64. Date: Mon, 22 Apr 2024 12:16:29 +0200
  65. Subject: [PATCH 2/5] daemon: Provide utility functions to get
  66.  |TOKEN_USER|/|TOKEN_PRIMARY_GROUP|
  67.  
  68. Provide utility functions |get_token_user_name()|+
  69. |get_token_primarygroup_name()| to get |TOKEN_USER|+
  70. |TOKEN_PRIMARY_GROUP| from a given token.
  71.  
  72. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  73. ---
  74. daemon/util.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++
  75.  daemon/util.h |  4 +++
  76.  2 files changed, 85 insertions(+)
  77.  
  78. diff --git a/daemon/util.c b/daemon/util.c
  79. index 741a653..1ea5cfd 100644
  80. --- a/daemon/util.c
  81. +++ b/daemon/util.c
  82. @@ -25,6 +25,7 @@
  83.  #include <stdio.h>
  84.  #include <stdlib.h>
  85.  #include <wincrypt.h> /* for Crypt*() functions */
  86. +#include <Lmcons.h>
  87.  
  88.  #include "daemon_debug.h"
  89.  #include "util.h"
  90. @@ -717,3 +718,83 @@ bool getwinntversionnnumbers(
  91.  
  92.      return true;
  93.  }
  94. +
  95. +/*
  96. + * Performance hack:
  97. + * GETTOKINFO_EXTRA_BUFFER - extra space for more data
  98. + * |GetTokenInformation()| for |TOKEN_USER| and |TOKEN_PRIMARY_GROUP|
  99. + * always fails in Win10 with |ERROR_INSUFFICIENT_BUFFER| if you
  100. + * just pass the |sizeof(TOKEN_*)| value. Instead of calling
  101. + * |GetTokenInformation()| with |NULL| arg to obtain the size to
  102. + * allocate we just provide 2048 bytes of extra space after the
  103. + * |TOKEN_*| size, and pray it is enough
  104. + */
  105. +#define GETTOKINFO_EXTRA_BUFFER (2048)
  106. +
  107. +bool get_token_user_name(HANDLE tok, char *out_buffer)
  108. +{
  109. +    DWORD tokdatalen;
  110. +    PTOKEN_USER ptuser;
  111. +    PSID pusid;
  112. +    DWORD namesize = UNLEN+1;
  113. +    char domainbuffer[UNLEN+1];
  114. +    DWORD domainbuffer_size = sizeof(domainbuffer);
  115. +    SID_NAME_USE name_use;
  116. +
  117. +    tokdatalen = sizeof(TOKEN_USER)+GETTOKINFO_EXTRA_BUFFER;
  118. +    ptuser = _alloca(tokdatalen);
  119. +    if (!GetTokenInformation(tok, TokenUser, ptuser,
  120. +        tokdatalen, &tokdatalen)) {
  121. +        eprintf("get_token_username: "
  122. +            "GetTokenInformation(tok=0x%p, TokenUser) failed, "
  123. +            "status=%d\n",
  124. +            (void *)tok, (int)GetLastError());
  125. +        return false;
  126. +    }
  127. +
  128. +    pusid = ptuser->User.Sid;
  129. +
  130. +    if (!LookupAccountSidA(NULL, pusid, out_buffer, &namesize,
  131. +        domainbuffer, &domainbuffer_size, &name_use)) {
  132. +        eprintf("get_token_user_name: "
  133. +            "LookupAccountSidA() failed, status=%d\n",
  134. +            (int)GetLastError());
  135. +        return false;
  136. +    }
  137. +
  138. +    return true;
  139. +}
  140. +
  141. +bool get_token_primarygroup_name(HANDLE tok, char *out_buffer)
  142. +{
  143. +    DWORD tokdatalen;
  144. +    PTOKEN_PRIMARY_GROUP ptpgroup;
  145. +    PSID pgsid;
  146. +    DWORD namesize = GNLEN+1;
  147. +    char domainbuffer[UNLEN+1];
  148. +    DWORD domainbuffer_size = sizeof(domainbuffer);
  149. +    SID_NAME_USE name_use;
  150. +
  151. +    tokdatalen = sizeof(TOKEN_PRIMARY_GROUP)+GETTOKINFO_EXTRA_BUFFER;
  152. +    ptpgroup = _alloca(tokdatalen);
  153. +    if (!GetTokenInformation(tok, TokenPrimaryGroup, ptpgroup,
  154. +        tokdatalen, &tokdatalen)) {
  155. +        eprintf("get_token_primarygroup_name: "
  156. +            "GetTokenInformation(tok=0x%p, TokenPrimaryGroup) failed, "
  157. +            "status=%d\n",
  158. +            (void *)tok, (int)GetLastError());
  159. +        return false;
  160. +    }
  161. +
  162. +    pgsid = ptpgroup->PrimaryGroup;
  163. +
  164. +    if (!LookupAccountSidA(NULL, pgsid, out_buffer, &namesize,
  165. +        domainbuffer, &domainbuffer_size, &name_use)) {
  166. +        eprintf("get_token_username: "
  167. +            "LookupAccountSidA() failed, status=%d\n",
  168. +            (int)GetLastError());
  169. +        return false;
  170. +    }
  171. +
  172. +    return true;
  173. +}
  174. diff --git a/daemon/util.h b/daemon/util.h
  175. index b1bdc8a..a09df70 100644
  176. --- a/daemon/util.h
  177. +++ b/daemon/util.h
  178. @@ -284,4 +284,8 @@ bool_t waitcriticalsection(LPCRITICAL_SECTION cs);
  179.  
  180.  bool getwinntversionnnumbers(DWORD *MajorVersionPtr, DWORD *MinorVersionPtr, DWORD *BuildNumberPtr);
  181.  
  182. +bool get_token_user_name(HANDLE tok, char *out_buffer);
  183. +bool get_token_primarygroup_name(HANDLE tok, char *out_buffer);
  184. +
  185. +
  186.  #endif /* !__NFS41_DAEMON_UTIL_H__ */
  187. --
  188. 2.43.0
  189.  
  190. From 51495ba84760d908224e4233ce50b672ff493e4e Mon Sep 17 00:00:00 2001
  191. From: Roland Mainz <roland.mainz@nrubsig.org>
  192. Date: Mon, 22 Apr 2024 12:20:00 +0200
  193. Subject: [PATCH 3/5] daemon: |logprintf()| should print current impersonated
  194.  user+primary group
  195.  
  196. |logprintf()| should print current impersonated user+primary group
  197.  
  198. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  199. ---
  200. daemon/daemon_debug.c | 13 +++++++++----
  201.  1 file changed, 9 insertions(+), 4 deletions(-)
  202.  
  203. diff --git a/daemon/daemon_debug.c b/daemon/daemon_debug.c
  204. index 83f8612..b35bfee 100644
  205. --- a/daemon/daemon_debug.c
  206. +++ b/daemon/daemon_debug.c
  207. @@ -89,23 +89,28 @@ void logprintf(LPCSTR format, ...)
  208.  {
  209.      SYSTEMTIME stime;
  210.      char username[UNLEN+1];
  211. -    DWORD username_len = sizeof(username);
  212. +    char groupname[GNLEN+1];
  213.  
  214.      GetLocalTime(&stime);
  215. -    if (!GetUserNameA(username, &username_len)) {
  216. +    if (!get_token_user_name(GetCurrentThreadEffectiveToken(),
  217. +        username)) {
  218.          (void)strcpy(username, "<unknown>");
  219.      }
  220. +    if (!get_token_primarygroup_name(GetCurrentThreadEffectiveToken(),
  221. +        groupname)) {
  222. +        (void)strcpy(groupname, "<unknown>");
  223. +    }
  224.  
  225.      va_list args;
  226.      va_start(args, format);
  227.      (void)fprintf(dlog_file,
  228.          "# LOG: ts=%04d-%02d-%02d_%02d:%02d:%02d:%04d"
  229. -        " thr=%04x user='%s' msg=",
  230. +        " thr=%04x user='%s'/'%s' msg=",
  231.          (int)stime.wYear, (int)stime.wMonth, (int)stime.wDay,
  232.          (int)stime.wHour, (int)stime.wMinute, (int)stime.wSecond,
  233.          (int)stime.wMilliseconds,
  234.          (int)GetCurrentThreadId(),
  235. -        username);
  236. +        username, groupname);
  237.      (void)vfprintf(dlog_file, format, args);
  238.      (void)fflush(dlog_file);
  239.      va_end(args);
  240. --
  241. 2.43.0
  242.  
  243. From 1081abedf16f90ed015ec96d13b0020036f76e7e Mon Sep 17 00:00:00 2001
  244. From: Roland Mainz <roland.mainz@nrubsig.org>
  245. Date: Mon, 22 Apr 2024 16:14:32 +0200
  246. Subject: [PATCH 4/5] daemon: |nfs41_client_owner()| should use faster
  247.  |get_token_user_name()|
  248.  
  249. |nfs41_client_owner()| should use faster |get_token_user_name()|
  250. instead of |GetUserNameA()|
  251.  
  252. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  253. ---
  254. daemon/nfs41_client.c | 14 +++++++++-----
  255.  1 file changed, 9 insertions(+), 5 deletions(-)
  256.  
  257. diff --git a/daemon/nfs41_client.c b/daemon/nfs41_client.c
  258. index d0306a0..2707414 100644
  259. --- a/daemon/nfs41_client.c
  260. +++ b/daemon/nfs41_client.c
  261. @@ -368,12 +368,16 @@ int nfs41_client_owner(
  262.      DWORD length;
  263.      const ULONGLONG time_created = GetTickCount64();
  264.      int status;
  265. -    char username[UNLEN + 1];
  266. -    DWORD len = UNLEN + 1;
  267. -
  268. -    if (!GetUserNameA(username, &len)) {
  269. +    char username[UNLEN+1];
  270. +
  271. +    /*
  272. +     * gisburn: What about primary group (for /usr/bin/newgrp
  273. +     * support) ?
  274. +     */
  275. +    if (!get_token_user_name(GetCurrentThreadEffectiveToken(),
  276. +        username)) {
  277.          status = GetLastError();
  278. -        eprintf("GetUserName() failed with %d\n", status);
  279. +        eprintf("get_token_user_name() failed with %d\n", status);
  280.          goto out;
  281.      }
  282.  
  283. --
  284. 2.43.0
  285.  
  286. From 0c83631ecc377864c2aca0d1a4c9a5bd7bfb230b Mon Sep 17 00:00:00 2001
  287. From: Roland Mainz <roland.mainz@nrubsig.org>
  288. Date: Mon, 22 Apr 2024 16:24:21 +0200
  289. Subject: [PATCH 5/5] daemon,sys: Add experimental support for
  290.  |setgid()|/newgrp(1)
  291.  
  292. Add experimental support for |setgid()|/newgrp(1).
  293. This is currently implemented as a hack via setatttr to change the
  294. owner_group of newly created files.
  295.  
  296. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  297. ---
  298. daemon/nfs41_daemon.c  | 54 +++++++++++++++++++++++++++++++++++-------
  299.  daemon/open.c          | 23 ++++++++++++++++++
  300.  nfs41_build_features.h |  6 +++++
  301.  sys/nfs41_driver.c     |  8 +++++++
  302.  4 files changed, 82 insertions(+), 9 deletions(-)
  303.  
  304. diff --git a/daemon/nfs41_daemon.c b/daemon/nfs41_daemon.c
  305. index 5a6bbc2..c7bef5f 100644
  306. --- a/daemon/nfs41_daemon.c
  307. +++ b/daemon/nfs41_daemon.c
  308. @@ -67,25 +67,59 @@ typedef struct _nfs41_process_thread {
  309.      uint32_t tid;
  310.  } nfs41_process_thread;
  311.  
  312. -static int map_current_user_to_ids(nfs41_idmapper *idmapper, uid_t *uid, gid_t *gid)
  313. +static int map_current_user_to_ids(nfs41_idmapper *idmapper, uid_t *puid, gid_t *pgid)
  314.  {
  315. -    char username[UNLEN + 1];
  316. -    DWORD len = UNLEN + 1;
  317. +    char username[UNLEN+1];
  318. +    char pgroupname[GNLEN+1];
  319.      int status = NO_ERROR;
  320. +    HANDLE impersonation_tok = GetCurrentThreadEffectiveToken();
  321. +    gid_t dummygid;
  322.  
  323. -    if (!GetUserNameA(username, &len)) {
  324. +    if (!get_token_user_name(impersonation_tok, username)) {
  325.          status = GetLastError();
  326. -        eprintf("map_current_user_to_ids: GetUserName() failed with %d\n", status);
  327. +        eprintf("map_current_user_to_ids: "
  328. +            "get_token_user_name() failed with %d\n", status);
  329.          goto out;
  330.      }
  331. -    DPRINTF(1, ("map_current_user_to_ids: mapping user '%s'\n", username));
  332.  
  333. -    if (nfs41_idmap_name_to_ids(idmapper, username, uid, gid)) {
  334. +    if (!get_token_primarygroup_name(impersonation_tok, pgroupname)) {
  335. +        status = GetLastError();
  336. +        eprintf("map_current_user_to_ids: "
  337. +            "get_token_primarygroup_name() failed with %d\n", status);
  338. +        goto out;
  339. +    }
  340. +
  341. +    if (nfs41_idmap_name_to_ids(idmapper, username, puid, &dummygid)) {
  342.          /* instead of failing for auth_sys, fall back to 'nobody' uid/gid */
  343. -        *uid = nfs41_dg.default_uid;
  344. -        *gid = nfs41_dg.default_gid;
  345. +        DPRINTF(1,
  346. +            ("map_current_user_to_ids: "
  347. +                "nfs41_idmap_name_to_ids(username='%s') failed, "
  348. +                "returning nobody/nogroup defaults\n",
  349. +                username));
  350. +        *puid = nfs41_dg.default_uid;
  351. +        *pgid = nfs41_dg.default_gid;
  352. +        status = NO_ERROR;
  353. +        goto out;
  354.      }
  355. +
  356. +    if (nfs41_idmap_group_to_gid(
  357. +        idmapper,
  358. +        pgroupname,
  359. +        pgid)) {
  360. +        DPRINTF(1,
  361. +            ("map_current_user_to_ids: "
  362. +                "nfs41_idmap_group_to_gid(pgroupname='%s') failed, "
  363. +                "returning nogroup\n",
  364. +                pgroupname));
  365. +        *pgid = nfs41_dg.default_gid;
  366. +    }
  367. +
  368.  out:
  369. +    DPRINTF(1,
  370. +        ("map_current_user_to_ids: "
  371. +            "mapping user=(name='%s' ==> uid=%d)/pgroup=(name='%s' ==> gid=%d)\n",
  372. +            username, (int)*puid,
  373. +            pgroupname, (int)*pgid));
  374.      return status;
  375.  }
  376.  
  377. @@ -649,6 +683,8 @@ VOID ServiceStart(DWORD argc, LPTSTR *argv)
  378.      DPRINTF(0, ("SID cache disabled\n"));
  379.  #endif /* NFS41_DRIVER_SID_CACHE */
  380.  
  381. +    logprintf("NFS client daemon starting...\n");
  382. +
  383.      /* acquire and store in global memory current dns domain name.
  384.       * needed for acls */
  385.      if (getdomainname()) {
  386. diff --git a/daemon/open.c b/daemon/open.c
  387. index 85f0bcc..814354f 100644
  388. --- a/daemon/open.c
  389. +++ b/daemon/open.c
  390. @@ -941,6 +941,29 @@ supersede_retry:
  391.              status = nfs_to_windows_error(status, ERROR_FILE_NOT_FOUND);
  392.              goto out_free_state;
  393.          } else {
  394. +#ifdef NFS41_DRIVER_SETGID_NEWGRP_SUPPORT
  395. +            /*
  396. +             * Hack: Support |setgid()|/newgrp(1) by fetching group
  397. +             * name from auth token for new files and do a "manual"
  398. +             * chgrp on the new file
  399. +             */
  400. +            if (create == OPEN4_CREATE) {
  401. +                nfs41_file_info createchgrpattrs = { 0 };
  402. +                createchgrpattrs.attrmask.count = 2;
  403. +                createchgrpattrs.attrmask.arr[1] |= FATTR4_WORD1_OWNER_GROUP;
  404. +                createchgrpattrs.owner_group = createchgrpattrs.owner_group_buf;
  405. +                (void)get_token_primarygroup_name(GetCurrentThreadEffectiveToken(),
  406. +                    createchgrpattrs.owner_group);
  407. +                (void)strcat(createchgrpattrs.owner_group, "@");
  408. +                (void)strcat(createchgrpattrs.owner_group,  nfs41dg->localdomain_name);
  409. +                DPRINTF(1, ("handle_open(): create(), groupname='%s'\n", createchgrpattrs.owner_group));
  410. +
  411. +                stateid_arg stateid;
  412. +                nfs41_open_stateid_arg(state, &stateid);
  413. +                (void)nfs41_setattr(state->session, &state->file, &stateid, &createchgrpattrs);
  414. +            }
  415. +#endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
  416. +
  417.              nfs_to_basic_info(state->file.name.name, &info, &args->basic_info);
  418.              nfs_to_standard_info(&info, &args->std_info);
  419.              args->mode = info.mode;
  420. diff --git a/nfs41_build_features.h b/nfs41_build_features.h
  421. index 2e18150..7b607ea 100644
  422. --- a/nfs41_build_features.h
  423. +++ b/nfs41_build_features.h
  424. @@ -93,4 +93,10 @@
  425.   */
  426.  #define NFS41_DRIVER_USE_LARGE_SOCKET_RCVSND_BUFFERS 1
  427.  
  428. +/*
  429. + * Support /usr/bin/newgrp&co, which have a non-default
  430. + * |TOKEN_PRIMARY_GROUP|
  431. + */
  432. +#define NFS41_DRIVER_SETGID_NEWGRP_SUPPORT 1
  433. +
  434.  #endif /* !_NFS41_DRIVER_BUILDFEATURES_ */
  435. diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c
  436. index f1135ad..b223d32 100644
  437. --- a/sys/nfs41_driver.c
  438. +++ b/sys/nfs41_driver.c
  439. @@ -41,7 +41,15 @@
  440.  #include "nfs41_build_features.h"
  441.  
  442.  
  443. +/*
  444. + * FIXME: NFS41_DRIVER_SETGID_NEWGRP_SUPPORT - we need the correct
  445. + * |TOKEN_PRIMARY_GROUP| for |setgid()|/newgrp(1)
  446. + * support, and |#define USE_MOUNT_SEC_CONTEXT| currently breaks
  447. + * that
  448. + */
  449. +#ifndef NFS41_DRIVER_SETGID_NEWGRP_SUPPORT
  450.  #define USE_MOUNT_SEC_CONTEXT
  451. +#endif
  452.  
  453.  /* debugging printout defines */
  454.  #define DEBUG_MARSHAL_HEADER
  455. --
  456. 2.43.0

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.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at