aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2015-01-03 15:54:04 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2015-01-03 15:54:04 +0100
commit8d547aca75f8b096976a472714241acd4328be46 (patch)
treecd7c4ba350c19f5369374302f7eb001e53cfe77e
parent31d6734457b9cafeeaa862750c2afa80aa67816c (diff)
downloadbusybox-w32-8d547aca75f8b096976a472714241acd4328be46.tar.gz
busybox-w32-8d547aca75f8b096976a472714241acd4328be46.tar.bz2
busybox-w32-8d547aca75f8b096976a472714241acd4328be46.zip
libpwdgrp: fix a memory leak in getXXnam (we did not save address of string buf)
function old new delta convert_to_struct 261 269 +8 const_sp_db 20 24 +4 const_pw_db 20 24 +4 const_gr_db 20 24 +4 tokenize 144 147 +3 parse_common 185 188 +3 get_S 82 85 +3 bb_internal_getpwent_r 188 185 -3 gr_off 4 - -4 getXXnam 171 165 -6 pw_off 7 - -7 getgrouplist_internal 237 229 -8 getXXnam_r 215 207 -8 sp_off 9 - -9 ------------------------------------------------------------------------------ (add/remove: 0/3 grow/shrink: 7/4 up/down: 29/-45) Total: -16 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--libpwdgrp/pwd_grp.c131
1 files changed, 74 insertions, 57 deletions
diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c
index 823884edc..6d938f621 100644
--- a/libpwdgrp/pwd_grp.c
+++ b/libpwdgrp/pwd_grp.c
@@ -32,69 +32,79 @@
32 32
33#include "libbb.h" 33#include "libbb.h"
34 34
35/* S = string not empty, s = string maybe empty,
36 * I = uid,gid, l = long maybe empty, m = members,
37 * r = reserved
38 */
39#define PW_DEF "SsIIsSS"
40#define GR_DEF "SsIm"
41#define SP_DEF "Ssllllllr"
42
43static const uint8_t pw_off[] ALIGN1 = {
44 offsetof(struct passwd, pw_name), /* 0 S */
45 offsetof(struct passwd, pw_passwd), /* 1 s */
46 offsetof(struct passwd, pw_uid), /* 2 I */
47 offsetof(struct passwd, pw_gid), /* 3 I */
48 offsetof(struct passwd, pw_gecos), /* 4 s */
49 offsetof(struct passwd, pw_dir), /* 5 S */
50 offsetof(struct passwd, pw_shell) /* 6 S */
51};
52static const uint8_t gr_off[] ALIGN1 = {
53 offsetof(struct group, gr_name), /* 0 S */
54 offsetof(struct group, gr_passwd), /* 1 s */
55 offsetof(struct group, gr_gid), /* 2 I */
56 offsetof(struct group, gr_mem) /* 3 m (char **) */
57};
58#if ENABLE_USE_BB_SHADOW
59static const uint8_t sp_off[] ALIGN1 = {
60 offsetof(struct spwd, sp_namp), /* 0 S Login name */
61 offsetof(struct spwd, sp_pwdp), /* 1 s Encrypted password */
62 offsetof(struct spwd, sp_lstchg), /* 2 l */
63 offsetof(struct spwd, sp_min), /* 3 l */
64 offsetof(struct spwd, sp_max), /* 4 l */
65 offsetof(struct spwd, sp_warn), /* 5 l */
66 offsetof(struct spwd, sp_inact), /* 6 l */
67 offsetof(struct spwd, sp_expire), /* 7 l */
68 offsetof(struct spwd, sp_flag) /* 8 r Reserved */
69};
70#endif
71
72struct const_passdb { 35struct const_passdb {
73 const char *filename; 36 const char *filename;
74 const uint8_t *off;
75 const char def[10]; 37 const char def[10];
38 const uint8_t off[9];
76 uint8_t numfields; 39 uint8_t numfields;
77 uint8_t size_of;
78}; 40};
79struct passdb { 41struct passdb {
80 const char *filename; 42 const char *filename;
81 const uint8_t *off;
82 const char def[10]; 43 const char def[10];
44 const uint8_t off[9];
83 uint8_t numfields; 45 uint8_t numfields;
84 uint8_t size_of;
85 FILE *fp; 46 FILE *fp;
86 void *malloced; 47 char *malloced;
48 char struct_result[0
49 | sizeof(struct passwd)
50 | sizeof(struct group)
51 IF_USE_BB_SHADOW( | sizeof(struct spwd) )
52 /* bitwise OR above is poor man's max(a,b,c) */
53 ];
87}; 54};
88 55
89static const struct const_passdb const_pw_db = { _PATH_PASSWD, pw_off, PW_DEF, sizeof(PW_DEF)-1, sizeof(struct passwd) }; 56/* S = string not empty, s = string maybe empty,
90static const struct const_passdb const_gr_db = { _PATH_GROUP , gr_off, GR_DEF, sizeof(GR_DEF)-1, sizeof(struct group) }; 57 * I = uid,gid, l = long maybe empty, m = members,
58 * r = reserved
59 */
60#define PW_DEF "SsIIsSS"
61#define GR_DEF "SsIm"
62#define SP_DEF "Ssllllllr"
63
64static const struct const_passdb const_pw_db = {
65 _PATH_PASSWD, PW_DEF,
66 {
67 offsetof(struct passwd, pw_name), /* 0 S */
68 offsetof(struct passwd, pw_passwd), /* 1 s */
69 offsetof(struct passwd, pw_uid), /* 2 I */
70 offsetof(struct passwd, pw_gid), /* 3 I */
71 offsetof(struct passwd, pw_gecos), /* 4 s */
72 offsetof(struct passwd, pw_dir), /* 5 S */
73 offsetof(struct passwd, pw_shell) /* 6 S */
74 },
75 sizeof(PW_DEF)-1
76};
77static const struct const_passdb const_gr_db = {
78 _PATH_GROUP, GR_DEF,
79 {
80 offsetof(struct group, gr_name), /* 0 S */
81 offsetof(struct group, gr_passwd), /* 1 s */
82 offsetof(struct group, gr_gid), /* 2 I */
83 offsetof(struct group, gr_mem) /* 3 m (char **) */
84 },
85 sizeof(GR_DEF)-1
86};
91#if ENABLE_USE_BB_SHADOW 87#if ENABLE_USE_BB_SHADOW
92static const struct const_passdb const_sp_db = { _PATH_SHADOW, sp_off, SP_DEF, sizeof(SP_DEF)-1, sizeof(struct spwd) }; 88static const struct const_passdb const_sp_db = {
89 _PATH_SHADOW, SP_DEF,
90 {
91 offsetof(struct spwd, sp_namp), /* 0 S Login name */
92 offsetof(struct spwd, sp_pwdp), /* 1 s Encrypted password */
93 offsetof(struct spwd, sp_lstchg), /* 2 l */
94 offsetof(struct spwd, sp_min), /* 3 l */
95 offsetof(struct spwd, sp_max), /* 4 l */
96 offsetof(struct spwd, sp_warn), /* 5 l */
97 offsetof(struct spwd, sp_inact), /* 6 l */
98 offsetof(struct spwd, sp_expire), /* 7 l */
99 offsetof(struct spwd, sp_flag) /* 8 r Reserved */
100 },
101 sizeof(SP_DEF)-1
102};
93#endif 103#endif
94 104
95/* We avoid having big global data. */ 105/* We avoid having big global data. */
96struct statics { 106struct statics {
97 /* It's ok to use same buffer (db[0].malloced) for getpwuid and getpwnam. 107 /* It's ok to use same buffer (db[0].struct_result) for getpwuid and getpwnam.
98 * Manpage says: 108 * Manpage says:
99 * "The return value may point to a static area, and may be overwritten 109 * "The return value may point to a static area, and may be overwritten
100 * by subsequent calls to getpwent(), getpwnam(), or getpwuid()." 110 * by subsequent calls to getpwent(), getpwnam(), or getpwuid()."
@@ -223,9 +233,15 @@ static char *parse_file(const char *filename,
223} 233}
224 234
225/* Convert passwd/group/shadow file record in buffer to a struct */ 235/* Convert passwd/group/shadow file record in buffer to a struct */
226static void *convert_to_struct(const char *def, const unsigned char *off, 236static void *convert_to_struct(struct passdb *db,
227 char *buffer, void *result) 237 char *buffer, void *result)
228{ 238{
239 const char *def = db->def;
240 const uint8_t *off = db->off;
241
242/* TODO? for consistency, zero out all fields */
243/* memset(result, 0, size_of_result);*/
244
229 for (;;) { 245 for (;;) {
230 void *member = (char*)result + (*off++); 246 void *member = (char*)result + (*off++);
231 247
@@ -282,7 +298,8 @@ static void *convert_to_struct(const char *def, const unsigned char *off,
282 298
283/****** getXXnam/id_r */ 299/****** getXXnam/id_r */
284 300
285static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, char *buffer, size_t buflen, 301static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos,
302 char *buffer, size_t buflen,
286 void *result) 303 void *result)
287{ 304{
288 void *struct_buf = *(void**)result; 305 void *struct_buf = *(void**)result;
@@ -299,7 +316,7 @@ static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, ch
299 errno = ERANGE; 316 errno = ERANGE;
300 } else { 317 } else {
301 memcpy(buffer, buf, size); 318 memcpy(buffer, buf, size);
302 *(void**)result = convert_to_struct(db->def, db->off, buffer, struct_buf); 319 *(void**)result = convert_to_struct(db, buffer, struct_buf);
303 } 320 }
304 free(buf); 321 free(buf);
305 } 322 }
@@ -310,8 +327,9 @@ static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, ch
310 return errno; 327 return errno;
311} 328}
312 329
313int FAST_FUNC getpwnam_r(const char *name, struct passwd *struct_buf, char *buffer, size_t buflen, 330int FAST_FUNC getpwnam_r(const char *name, struct passwd *struct_buf,
314 struct passwd **result) 331 char *buffer, size_t buflen,
332 struct passwd **result)
315{ 333{
316 /* Why the "store buffer address in result" trick? 334 /* Why the "store buffer address in result" trick?
317 * This way, getXXnam_r has the same ABI signature as getpwnam_r, 335 * This way, getXXnam_r has the same ABI signature as getpwnam_r,
@@ -357,7 +375,7 @@ static int FAST_FUNC getXXent_r(void *struct_buf, char *buffer, size_t buflen,
357 errno = ERANGE; 375 errno = ERANGE;
358 } else { 376 } else {
359 memcpy(buffer, buf, size); 377 memcpy(buffer, buf, size);
360 *(void**)result = convert_to_struct(db->def, db->off, buffer, struct_buf); 378 *(void**)result = convert_to_struct(db, buffer, struct_buf);
361 } 379 }
362 free(buf); 380 free(buf);
363 } 381 }
@@ -393,12 +411,11 @@ static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos)
393 close_on_exec_on(fileno(db->fp)); 411 close_on_exec_on(fileno(db->fp));
394 } 412 }
395 413
396 free(db->malloced);
397 db->malloced = NULL;
398 buf = parse_common(db->fp, db->filename, db->numfields, name, db_and_field_pos & 3); 414 buf = parse_common(db->fp, db->filename, db->numfields, name, db_and_field_pos & 3);
399 if (buf) { 415 if (buf) {
400 db->malloced = xzalloc(db->size_of); 416 free(db->malloced);
401 result = convert_to_struct(db->def, db->off, buf, db->malloced); 417 db->malloced = buf;
418 result = convert_to_struct(db, buf, db->struct_result);
402 } 419 }
403 return result; 420 return result;
404} 421}
@@ -465,7 +482,7 @@ static gid_t* FAST_FUNC getgrouplist_internal(int *ngroups_ptr,
465 while ((buf = parse_common(fp, _PATH_GROUP, sizeof(GR_DEF)-1, NULL, 0)) != NULL) { 482 while ((buf = parse_common(fp, _PATH_GROUP, sizeof(GR_DEF)-1, NULL, 0)) != NULL) {
466 char **m; 483 char **m;
467 struct group group; 484 struct group group;
468 if (!convert_to_struct(GR_DEF, gr_off, buf, &group)) 485 if (!convert_to_struct(&S.db[1], buf, &group))
469 goto next; 486 goto next;
470 if (group.gr_gid == gid) 487 if (group.gr_gid == gid)
471 goto next; 488 goto next;