Skip to content

Commit 20c1bb2

Browse files
committed
libnss_tcb: Match interfaces with NSS documention.
According to [1] the interfaces provided should be of return-type 'enum nss_status', and take 'int *errnop' as the fourth (and last) parameter. Additionally the returned status values should be accompanied by a corresponding ERRNO value [2] passed by the errnop pointer. [1] https://www.gnu.org/software/libc/manual/html_node/NSS-Module-Function-Internals.html [2] https://www.gnu.org/software/libc/manual/html_node/NSS-Modules-Interface.html Signed-off-by: Björn Esser <[email protected]>
1 parent b6ce07b commit 20c1bb2

File tree

2 files changed

+61
-21
lines changed

2 files changed

+61
-21
lines changed

ChangeLog

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
2024-12-20 Björn Esser <besser82 at fedoraproject.org>
22

3+
libnss_tcb: Match interfaces with NSS documention.
4+
According to [1] the interfaces provided should be of return-type
5+
'enum nss_status', and take 'int *errnop' as the fourth (and last)
6+
parameter. Additionally the returned status values should be
7+
accompanied by a corresponding ERRNO value [2] passed by the errnop
8+
pointer.
9+
[1] https://www.gnu.org/software/libc/manual/html_node/NSS-Module-Function-Internals.html
10+
[2] https://www.gnu.org/software/libc/manual/html_node/NSS-Modules-Interface.html
11+
* libs/nss.c (_nss_tcb_setspent): Adapt return-type and use return
12+
values from documented macro.
13+
(_nss_tcb_endspent): Likewise.
14+
(_nss_tcb_getspnam_r): Adapt return-type, change fourth parameter
15+
to be 'int *errnop', use return values from documented macros, and
16+
set proper errno in errnop before returning.
17+
(_nss_tcb_getspent_r): Likewise.
18+
319
libnss_tcb: Disallow potentially-malicious user names in getspnam(3).
420
IEEE Std 1003.1-2001 allows only the following characters to appear
521
in group- and usernames: letters, digits, underscores, periods,

libs/nss.c

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,27 @@
1313

1414
static __thread DIR *tcbdir = NULL;
1515

16-
int _nss_tcb_setspent(void)
16+
enum nss_status _nss_tcb_setspent(void)
1717
{
1818
if (!tcbdir) {
1919
tcbdir = opendir(TCB_DIR);
2020
if (!tcbdir)
2121
return NSS_STATUS_UNAVAIL;
2222

23-
return 1;
23+
return NSS_STATUS_SUCCESS;
2424
}
2525

2626
rewinddir(tcbdir);
27-
return 1;
27+
return NSS_STATUS_SUCCESS;
2828
}
2929

30-
int _nss_tcb_endspent(void)
30+
enum nss_status _nss_tcb_endspent(void)
3131
{
3232
if (tcbdir) {
3333
closedir(tcbdir);
3434
tcbdir = NULL;
3535
}
36-
return 1;
36+
return NSS_STATUS_SUCCESS;
3737
}
3838

3939
/******************************************************************************
@@ -91,57 +91,76 @@ static FILE *tcb_safe_open(const char *file, const char *name)
9191
return f;
9292
}
9393

94-
int _nss_tcb_getspnam_r(const char *name, struct spwd *__result_buf,
95-
char *__buffer, size_t __buflen, struct spwd **__result)
94+
enum nss_status _nss_tcb_getspnam_r(const char *name,
95+
struct spwd *__result_buf, char *__buffer, size_t __buflen, int *__errnop)
9696
{
9797
FILE *f;
9898
char *file;
9999
int retval, saved_errno;
100+
struct spwd **result_buf_ptr = NULL;
100101

101102
/* Disallow potentially-malicious user names */
102103
if (!is_valid_username(name)) {
103-
errno = ENOENT;
104+
/* we don't serve an entry here */
105+
*__errnop = ENOENT;
104106
return NSS_STATUS_NOTFOUND;
105107
}
106108

107-
if (asprintf(&file, TCB_FMT, name) < 0)
109+
if (asprintf(&file, TCB_FMT, name) < 0) {
110+
/* retry, as malloc or another resource has failed */
111+
*__errnop = EAGAIN;
108112
return NSS_STATUS_TRYAGAIN;
113+
}
114+
109115
f = tcb_safe_open(file, name);
110116
free(file);
111-
if (!f)
112-
return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL;
117+
if (!f) {
118+
/* $user/shadow not existing */
119+
*__errnop = ENOENT;
120+
return NSS_STATUS_UNAVAIL;
121+
}
113122

114-
retval = fgetspent_r(f, __result_buf, __buffer, __buflen, __result);
123+
retval = fgetspent_r(f, __result_buf, __buffer,
124+
__buflen, result_buf_ptr);
115125
saved_errno = errno;
116126
fclose(f);
117127
errno = saved_errno;
118128
if (!retval)
119129
return NSS_STATUS_SUCCESS;
120130

121-
switch (saved_errno) {
122-
case 0:
123-
return NSS_STATUS_SUCCESS;
124-
131+
/* real error number is retval from fgetspent_r() */
132+
*__errnop = retval;
133+
switch (retval) {
125134
case ENOENT:
135+
/* if the file would not exist, we would have already
136+
bailed out with ENOENT/NSS_STATUS_UNAVAIL immediately
137+
after the call to tcb_safe_open() */
126138
return NSS_STATUS_NOTFOUND;
127139

140+
case EAGAIN:
141+
/* ressources are temporary not available */
142+
return NSS_STATUS_TRYAGAIN;
143+
128144
case ERANGE:
145+
/* __buffer too small */
129146
return NSS_STATUS_TRYAGAIN;
130147

131148
default:
149+
/* something serious, but we can't help it */
132150
return NSS_STATUS_UNAVAIL;
133151
}
134152
}
135153

136-
int _nss_tcb_getspent_r(struct spwd *__result_buf,
137-
char *__buffer, size_t __buflen, struct spwd **__result)
154+
enum nss_status _nss_tcb_getspent_r(struct spwd *__result_buf,
155+
char *__buffer, size_t __buflen, int *__errnop)
138156
{
139157
struct dirent *result;
140158
off_t currpos;
141159
int retval, saved_errno;
142160

143161
if (!tcbdir) {
144-
errno = ENOENT;
162+
/* tcbdir does not exist */
163+
*__errnop = ENOENT;
145164
return NSS_STATUS_UNAVAIL;
146165
}
147166

@@ -154,21 +173,26 @@ int _nss_tcb_getspent_r(struct spwd *__result_buf,
154173
closedir(tcbdir);
155174
errno = saved_errno;
156175
tcbdir = NULL;
176+
/* cannot iterate tcbdir */
177+
*__errnop = ENOENT;
157178
return NSS_STATUS_UNAVAIL;
158179
}
159180
if (!result) {
160181
closedir(tcbdir);
161-
errno = ENOENT;
182+
errno = saved_errno;
162183
tcbdir = NULL;
184+
/* we have no more entries in tcbdir */
185+
*__errnop = ENOENT;
163186
return NSS_STATUS_NOTFOUND;
164187
}
165188
errno = saved_errno;
166189
} while (!strcmp(result->d_name, ".") ||
167190
!strcmp(result->d_name, "..") || result->d_name[0] == ':');
168191

169192
retval = _nss_tcb_getspnam_r(result->d_name, __result_buf, __buffer,
170-
__buflen, __result);
193+
__buflen, __errnop);
171194

195+
/* __errnop has already been set by _nss_tcb_getspnam_r() */
172196
switch (retval) {
173197
case NSS_STATUS_SUCCESS:
174198
return NSS_STATUS_SUCCESS;

0 commit comments

Comments
 (0)