Merge ~ahasenack/ubuntu/+source/nfs-utils:bionic-thread-safety-gssd-1927745 into ubuntu/+source/nfs-utils:ubuntu/bionic-devel

Proposed by Andreas Hasenack
Status: Merged
Approved by: Andreas Hasenack
Approved revision: 5a5c61e7c66b1f61826313692d359985eceee2d1
Merged at revision: 5a5c61e7c66b1f61826313692d359985eceee2d1
Proposed branch: ~ahasenack/ubuntu/+source/nfs-utils:bionic-thread-safety-gssd-1927745
Merge into: ubuntu/+source/nfs-utils:ubuntu/bionic-devel
Diff against target: 174 lines (+146/-0)
4 files modified
debian/changelog (+9/-0)
debian/patches/0010-gssd-replace-non-thread-safe-strtok-with-strsep.patch (+42/-0)
debian/patches/0011-gssd-Duplicate-the-upcall-string-for-error-messages.patch (+93/-0)
debian/patches/series (+2/-0)
Reviewer Review Type Date Requested Status
Sergio Durigan Junior (community) Approve
Canonical Server Pending
Review via email: mp+402515@code.launchpad.net

Description of the change

The linked bug has the SRU template filled in.

PPA with test packages: https://launchpad.net/~ahasenack/+archive/ubuntu/gssd-upcall-1927745

Note: it's a race condition and the supplied test doesn't always catch it. Sometimes I get it right away, other times I leave it running for an hour and nothing happens.

I had more success with reproducing the problem once I increased the number of cores available to the VM. I used 4.

This involves NFSv4 with kerberos, but I think I narrowed the setup down enough for an SRU test case. I may update the test case a bit still if I find a way to make the error happen more quickly, or more realiably.

I took the same patches as debian, which are in our focal+ packages, and just updated the DEP3 header with a link to this bug, and updated the "Last-Updated" field.

To post a comment you must log in.
Revision history for this message
Andreas Hasenack (ahasenack) wrote :

DEP8 passed:
autopkgtest [15:19:11]: test local-server-client: [-----------------------
bash: line 1: 29878 Killed /tmp/autopkgtest.REnxBo/build.2Ib/real-tree/debian/tests/local-server-client 2> >(tee -a /tmp/autopkgtest.REnxBo/local-server-client-stderr >&2) > >(tee -a /tmp/autopkgtest.REnxBo/local-server-client-stdout)
autopkgtest [15:19:11]: test process requested reboot with marker boot1
autopkgtest-virt-ssh: WARNING: ssh connection failed. Retrying in 3 seconds...
localhost:/home on /mnt/nfs_home type nfs4 (rw,relatime,vers=4.2,rsize=262144,wsize=262144,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=127.0.0.1,local_lock=none,addr=127.0.0.1)
localhost:/var/log on /mnt/nfs_log type nfs4 (rw,relatime,vers=4.2,rsize=262144,wsize=262144,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=127.0.0.1,local_lock=none,addr=127.0.0.1)
autopkgtest [15:19:28]: test local-server-client: -----------------------]
autopkgtest [15:19:28]: test local-server-client: - - - - - - - - - - results - - - - - - - - - -
local-server-client PASS
autopkgtest [15:19:28]: @@@@@@@@@@@@@@@@@@@@ summary
local-server-client PASS
autopkgtest [15:19:28]: Binaries: resetting testbed apt configuration
Hit:1 http://br.archive.ubuntu.com/ubuntu bionic InRelease
Hit:2 http://br.archive.ubuntu.com/ubuntu bionic-updates InRelease
Hit:3 http://br.archive.ubuntu.com/ubuntu bionic-backports InRelease
Hit:4 http://br.archive.ubuntu.com/ubuntu bionic-security InRelease
Reading package lists...

I thought that "Killed" message odd, but it's also present in autopkgtest.ubuntu.com runs: https://autopkgtest.ubuntu.com/results/autopkgtest-bionic/bionic/amd64/n/nfs-utils/20201210_022246_2218d@/log.gz

I think it's from the reboot.

Revision history for this message
Sergio Durigan Junior (sergiodj) wrote :

I'll review this one.

Revision history for this message
Sergio Durigan Junior (sergiodj) wrote :

Thanks for the MP, Andreas.

I was able to reproduce the bug locally by following the SRU template. I have a few comments about it:

- I had to resort to "hostnamectl set-hostname foo.example.com" in order to get the FQDN properly working. Maybe it's worth mentioning this there.

- Something I also did while trying to reproduce the bug was to invoke the "./bz1419280_test_threads" in two terminals simultaneously. I don't know if this helps or not, but it seemed to trigger the problem faster.

- LXD will create VMs using only one core by default, it seems. I think it's also worth mentioning that doing "lxc config set vm-name limits.cpu=4" is a good idea before running anything.

Either way, it is obvious that using strtok(3) in a threaded application is a bad idea. I reviewed the patches and they look fine to me.

I double-checked that the package builds fine and the autopkgtest run is still succeeding.

I'm leaving two minor comments in the code, but other than that the MP LGTM. Feel free to proceed after you address them.

review: Approve
Revision history for this message
Andreas Hasenack (ahasenack) wrote :

I eventually remembered we have bileto, and started https://bileto.ubuntu.com/#/ticket/4551, but I don't know where the test run is. It's not in /running, nor are there any results yet.

Revision history for this message
Andreas Hasenack (ahasenack) wrote :

> - Something I also did while trying to reproduce the bug was to invoke the "./bz1419280_test_threads" in two terminals simultaneously. I don't know if this helps or not, but it seemed to trigger the problem faster.

This will be a false positive, unless you checked the ps output and confirmed that stat_as was in D state.

Revision history for this message
Andreas Hasenack (ahasenack) wrote :

> - I had to resort to "hostnamectl set-hostname foo.example.com" in order to get the FQDN properly working. Maybe it's worth mentioning this there.

Yeah, will do. This is particularly true if you miss the resolv.conf change, or if dhcp renewed the lease while you are testing and it resets the domain search. It's messy to automate this well enough for a test case ;)

Revision history for this message
Sergio Durigan Junior (sergiodj) wrote :

> > - Something I also did while trying to reproduce the bug was to invoke the
> "./bz1419280_test_threads" in two terminals simultaneously. I don't know if
> this helps or not, but it seemed to trigger the problem faster.
>
> This will be a false positive, unless you checked the ps output and confirmed
> that stat_as was in D state.

Ah, fair enough. Yeah, stat_as was in D state, but you've got a point here, so it's better to stick to the original reproduction steps.

Revision history for this message
Sergio Durigan Junior (sergiodj) :
Revision history for this message
Andreas Hasenack (ahasenack) wrote :

Ok, review points addressed, and I also updated the bug description

Revision history for this message
Sergio Durigan Junior (sergiodj) wrote :

LGTM, thanks.

review: Approve
Revision history for this message
Andreas Hasenack (ahasenack) wrote :

I'm force-pushing the upload tag, turns out there was another upload in unapproved due to https://bugs.launchpad.net/ubuntu/+source/nfs-utils/+bug/1918141. I talked with Robie and he rejected it, since there will be more discussions about that bug in particular.

$ git push pkg upload/1%1.3.4-2.1ubuntu5.4 --force
Enumerating objects: 23, done.
Counting objects: 100% (23/23), done.
Delta compression using up to 4 threads
Compressing objects: 100% (18/18), done.
Writing objects: 100% (18/18), 3.27 KiB | 197.00 KiB/s, done.
Total 18 (delta 13), reused 0 (delta 0), pack-reused 0
To ssh://git.launchpad.net/~usd-import-team/ubuntu/+source/nfs-utils
 + 6bf167f6...f57b97a7 upload/1%1.3.4-2.1ubuntu5.4 -> upload/1%1.3.4-2.1ubuntu5.4 (forced update)

Uploaded:
$ dput ubuntu nfs-utils_1.3.4-2.1ubuntu5.4_source.changes
Checking signature on .changes
gpg: /home/andreas/git/packages/nfs-utils/nfs-utils_1.3.4-2.1ubuntu5.4_source.changes: Valid signature from AC983EB5BF6BCBA9
Checking signature on .dsc
gpg: /home/andreas/git/packages/nfs-utils/nfs-utils_1.3.4-2.1ubuntu5.4.dsc: Valid signature from AC983EB5BF6BCBA9
Uploading to ubuntu (via ftp to upload.ubuntu.com):
  Uploading nfs-utils_1.3.4-2.1ubuntu5.4.dsc: done.
  Uploading nfs-utils_1.3.4-2.1ubuntu5.4.debian.tar.bz2: done.
  Uploading nfs-utils_1.3.4-2.1ubuntu5.4_source.buildinfo: done.
  Uploading nfs-utils_1.3.4-2.1ubuntu5.4_source.changes: done.
Successfully uploaded packages.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index b235caf..7fe02e0 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,12 @@
6+nfs-utils (1:1.3.4-2.1ubuntu5.4) bionic; urgency=medium
7+
8+ * Don't use non-thread-safe strtok() in handle_gssd_upcall()
9+ (LP: #1927745):
10+ - d/p/0010-gssd-replace-non-thread-safe-strtok-with-strsep.patch
11+ - d/p/0011-gssd-Duplicate-the-upcall-string-for-error-messages.patch
12+
13+ -- Andreas Hasenack <andreas@canonical.com> Fri, 07 May 2021 11:42:14 -0300
14+
15 nfs-utils (1:1.3.4-2.1ubuntu5.3) bionic-security; urgency=medium
16
17 * SECURITY UPDATE: privilege escalation via directory permissions
18diff --git a/debian/patches/0010-gssd-replace-non-thread-safe-strtok-with-strsep.patch b/debian/patches/0010-gssd-replace-non-thread-safe-strtok-with-strsep.patch
19new file mode 100644
20index 0000000..a7da3da
21--- /dev/null
22+++ b/debian/patches/0010-gssd-replace-non-thread-safe-strtok-with-strsep.patch
23@@ -0,0 +1,42 @@
24+From: Frank Sorenson <sorenson@redhat.com>
25+Date: Wed, 15 Feb 2017 10:36:47 -0500
26+Subject: gssd: replace non-thread-safe strtok with strsep
27+
28+gssd uses the non-thread-safe strtok() function, which
29+can lead to incorrect program behavior.
30+
31+Replace strtok() with the thread-safe strsep().
32+
33+Signed-off-by: Frank Sorenson <sorenson@redhat.com>
34+Signed-off-by: Steve Dickson <steved@redhat.com>
35+
36+Origin: upstream, http://git.linux-nfs.org/?p=steved/nfs-utils.git;a=commitdiff;h=5ae8be8
37+Bug-Redhat: https://bugzilla.redhat.com/show_bug.cgi?id=1419280
38+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=895381
39+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1927745
40+Last-Update: 2020-05-07
41+
42+---
43+ utils/gssd/gssd_proc.c | 3 ++-
44+ 1 file changed, 2 insertions(+), 1 deletion(-)
45+
46+diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
47+index d74d3724..30c6aceb 100644
48+--- a/utils/gssd/gssd_proc.c
49++++ b/utils/gssd/gssd_proc.c
50+@@ -729,10 +729,11 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
51+ char *target = NULL;
52+ char *service = NULL;
53+ char *enctypes = NULL;
54++ char *pbuf = info->lbuf;
55+
56+ printerr(2, "\n%s: '%s' (%s)\n", __func__, info->lbuf, clp->relpath);
57+
58+- for (p = strtok(info->lbuf, " "); p; p = strtok(NULL, " ")) {
59++ while ((p = strsep(&pbuf, " "))) {
60+ if (!strncmp(p, "mech=", strlen("mech=")))
61+ mech = p + strlen("mech=");
62+ else if (!strncmp(p, "uid=", strlen("uid=")))
63+--
64+2.20.1
65+
66diff --git a/debian/patches/0011-gssd-Duplicate-the-upcall-string-for-error-messages.patch b/debian/patches/0011-gssd-Duplicate-the-upcall-string-for-error-messages.patch
67new file mode 100644
68index 0000000..1ce7320
69--- /dev/null
70+++ b/debian/patches/0011-gssd-Duplicate-the-upcall-string-for-error-messages.patch
71@@ -0,0 +1,93 @@
72+From: Frank Sorenson <sorenson@redhat.com>
73+Date: Wed, 15 Feb 2017 10:38:53 -0500
74+Subject: gssd: Duplicate the upcall string for error messages
75+
76+strsep() modifies the input string, so error messages
77+may output only part of the upcall string.
78+
79+Make a copy of the upcall string, and use that in any
80+error messages.
81+
82+Signed-off-by: Frank Sorenson <sorenson@redhat.com>
83+Signed-off-by: Steve Dickson <steved@redhat.com>
84+
85+Origin: upstream, http://git.linux-nfs.org/?p=steved/nfs-utils.git;a=commitdiff;h=0a4f5e4
86+Bug-Redhat: https://bugzilla.redhat.com/show_bug.cgi?id=1419280
87+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=895381
88+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1927745
89+Last-Update: 2021-05-07
90+
91+---
92+ utils/gssd/gssd_proc.c | 17 +++++++++++++----
93+ 1 file changed, 13 insertions(+), 4 deletions(-)
94+
95+diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
96+index 30c6aceb..4fc81c30 100644
97+--- a/utils/gssd/gssd_proc.c
98++++ b/utils/gssd/gssd_proc.c
99+@@ -729,10 +729,17 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
100+ char *target = NULL;
101+ char *service = NULL;
102+ char *enctypes = NULL;
103++ char *upcall_str;
104+ char *pbuf = info->lbuf;
105+
106+ printerr(2, "\n%s: '%s' (%s)\n", __func__, info->lbuf, clp->relpath);
107+
108++ upcall_str = strdup(info->lbuf);
109++ if (upcall_str == NULL) {
110++ printerr(0, "ERROR: malloc failure\n");
111++ goto out_nomem;
112++ }
113++
114+ while ((p = strsep(&pbuf, " "))) {
115+ if (!strncmp(p, "mech=", strlen("mech=")))
116+ mech = p + strlen("mech=");
117+@@ -749,7 +756,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
118+ if (!mech || strlen(mech) < 1) {
119+ printerr(0, "WARNING: handle_gssd_upcall: "
120+ "failed to find gss mechanism name "
121+- "in upcall string '%s'\n", info->lbuf);
122++ "in upcall string '%s'\n", upcall_str);
123+ goto out;
124+ }
125+
126+@@ -762,7 +769,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
127+ if (!uidstr) {
128+ printerr(0, "WARNING: handle_gssd_upcall: "
129+ "failed to find uid "
130+- "in upcall string '%s'\n", info->lbuf);
131++ "in upcall string '%s'\n", upcall_str);
132+ goto out;
133+ }
134+
135+@@ -775,7 +782,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
136+ if (target && strlen(target) < 1) {
137+ printerr(0, "WARNING: handle_gssd_upcall: "
138+ "failed to parse target name "
139+- "in upcall string '%s'\n", info->lbuf);
140++ "in upcall string '%s'\n", upcall_str);
141+ goto out;
142+ }
143+
144+@@ -790,7 +797,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
145+ if (service && strlen(service) < 1) {
146+ printerr(0, "WARNING: handle_gssd_upcall: "
147+ "failed to parse service type "
148+- "in upcall string '%s'\n", info->lbuf);
149++ "in upcall string '%s'\n", upcall_str);
150+ goto out;
151+ }
152+
153+@@ -803,6 +810,8 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
154+ do_error_downcall(clp->gssd_fd, uid, -EACCES);
155+ }
156+ out:
157++ free(upcall_str);
158++out_nomem:
159+ free(info);
160+ return;
161+ }
162+--
163+2.20.1
164+
165diff --git a/debian/patches/series b/debian/patches/series
166index 4d44f03..0ff8b7f 100644
167--- a/debian/patches/series
168+++ b/debian/patches/series
169@@ -18,3 +18,5 @@ uint16-max.diff
170 fix-whitespaces-in-nfs-server.service.patch
171 nfsiostat-replace-list-reserved-word.patch
172 CVE-2019-3689.patch
173+0010-gssd-replace-non-thread-safe-strtok-with-strsep.patch
174+0011-gssd-Duplicate-the-upcall-string-for-error-messages.patch

Subscribers

People subscribed via source and target branches