From f9008d6e0a1a9a0899e57f5d4d4f768812dd6fca Mon Sep 17 00:00:00 2001 From: Hyotaek Shim Date: Fri, 17 Nov 2017 18:21:49 +0900 Subject: [PATCH] Make tzplatform_context_set_user() to be multi-thread-safe Change-Id: Ica378036e8bbe0756543d3ec796f7549b9f4f1c7 Signed-off-by: Hyotaek Shim (cherry picked from commit eb4ba339773587498112bf177b87376c4d4a078b) --- src/buffer.h | 2 +- src/context.c | 4 --- src/context.h | 11 ++++++++ src/init.c | 2 +- src/passwd.c | 83 ++++++++++++++++++++++++++++---------------------------- src/passwd.h | 10 ++++--- src/shared-api.c | 8 ++---- 7 files changed, 64 insertions(+), 56 deletions(-) diff --git a/src/buffer.h b/src/buffer.h index 704f51e..bc3116e 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -28,7 +28,7 @@ struct buffer { char *buffer; /* start address */ size_t length; /* length in byte */ - int mapped; /* is memory mapped */ + int mapped; /* is memory mapped */ }; /* diff --git a/src/context.c b/src/context.c index a0e1bb3..3b0fd5e 100644 --- a/src/context.c +++ b/src/context.c @@ -22,8 +22,6 @@ * */ - - #define _GNU_SOURCE #ifdef HAVE_CONFIG_H @@ -41,7 +39,6 @@ #include "foreign.h" #include "context.h" - uid_t get_uid(struct tzplatform_context *context) { uid_t result; @@ -72,4 +69,3 @@ gid_t get_gid(struct tzplatform_context *context) return getgid(); } #endif - diff --git a/src/context.h b/src/context.h index fdf0b69..f6c3fa4 100644 --- a/src/context.h +++ b/src/context.h @@ -24,6 +24,10 @@ #ifndef CONTEXT_H #define CONTEXT_H +#include "foreign.h" +#include "buffer.h" +#include "tzplatform_variables.h" + #ifndef HEAP_H #error "you should include heap.h" #endif @@ -36,6 +40,12 @@ enum STATE { RESET = 0, ERROR, VALID }; #define _USER_NOT_SET_ ((uid_t)-1) +struct pw { + struct buffer buffer; + size_t pos, lengths[7]; + const char *starts[7]; +}; + struct tzplatform_context { #ifndef NOT_MULTI_THREAD_SAFE pthread_mutex_t mutex; @@ -44,6 +54,7 @@ struct tzplatform_context { uid_t user; struct heap heap; const char *values[_TZPLATFORM_VARIABLES_COUNT_]; + struct pw pw; }; uid_t get_uid(struct tzplatform_context *context); diff --git a/src/init.c b/src/init.c index b431098..169f919 100644 --- a/src/init.c +++ b/src/init.c @@ -186,7 +186,7 @@ static void foreignpw(struct reading *reading) if (n) { array[n] = NULL; - if (pw_get(&reading->context->heap, array) == 0) { + if (pw_get(reading->context, &reading->context->heap, array) == 0) { #if _FOREIGN_HAS_(HOME) if (uid.set) reading->dynvars[HOME] = uid.home; diff --git a/src/passwd.c b/src/passwd.c index 325cc30..629664d 100644 --- a/src/passwd.c +++ b/src/passwd.c @@ -43,44 +43,42 @@ enum { iname, ipasswd, iuid, igid, icmt, idir, ishell }; static const char pwfile[] = "/etc/passwd"; -static struct buffer buffer; -static size_t pos, lengths[7]; -static const char *starts[7]; -#define is(s, i) (!strncmp(s, starts[i], lengths[i]) && !s[lengths[i]]) +#define is(s, i) (!strncmp(s, context->pw.starts[i], context->pw.lengths[i]) && !s[context->pw.lengths[i]]) /* open the passwd file */ -static int oppw() +static int oppw(struct tzplatform_context *context) { - pos = 0; - return buffer_create(&buffer, pwfile); + context->pw.pos = 0; + return buffer_create(&context->pw.buffer, pwfile); } /* close the passwd file */ -static void clpw() +static void clpw(struct tzplatform_context *context) { - buffer_destroy(&buffer); + buffer_destroy(&context->pw.buffer); } /* read the passwd file */ -static int rdpw() +static int rdpw(struct tzplatform_context *context) { int col = 0; - const char *head = buffer.buffer + pos; - const char *end = buffer.buffer + buffer.length; + struct pw *pw = &context->pw; + const char *head = pw->buffer.buffer + pw->pos; + const char *end = pw->buffer.buffer + pw->buffer.length; while (head != end) { - starts[col] = head; + pw->starts[col] = head; while (head != end && *head != ':' && *head != '\n') head++; - lengths[col] = head - starts[col]; + pw->lengths[col] = head - pw->starts[col]; col++; if (col == 7) { if (head == end) { - pos = head - buffer.buffer; + pw->pos = head - pw->buffer.buffer; return 1; } if (*head == '\n') { head++; - pos = head - buffer.buffer; + pw->pos = head - pw->buffer.buffer; return 1; } while (head != end && *head != '\n') head++; @@ -93,31 +91,32 @@ static int rdpw() } } } - pos = head - buffer.buffer; + pw->pos = head - pw->buffer.buffer; return 0; } -int pw_get(struct heap *heap, struct pwget **items) +int pw_get(struct tzplatform_context *context, struct heap *heap, struct pwget **items) { size_t user, home; int result; int i, n, s; + struct pw *pw = &context->pw; for (n = 0 ; items[n] != NULL ; n++) items[n]->set = 0; - result = oppw(); + result = oppw(context); if (result == 0) { s = n; - while (s && rdpw()) { + while (s && rdpw(context)) { user = home = HNULL; for (i = 0 ; i < n ; i++) { if (!items[i]->set && is(items[i]->id, iuid)) { if (user == HNULL) { user = heap_strndup(heap, - starts[iname], lengths[iname]); + pw->starts[iname], pw->lengths[iname]); home = heap_strndup(heap, - starts[idir], lengths[idir]); + pw->starts[idir], pw->lengths[idir]); } items[i]->set = 1; items[i]->user = user; @@ -126,55 +125,57 @@ int pw_get(struct heap *heap, struct pwget **items) } } } - clpw(); + clpw(context); } return result; } -int pw_has_uid(uid_t uid) +int pw_has_uid(struct tzplatform_context *context, uid_t uid) { - if (oppw() == 0) { - while (rdpw()) { - if (lengths[iuid] && (int)uid == atoi(starts[iuid])) { - clpw(); + struct pw *pw = &context->pw; + + if (oppw(context) == 0) { + while (rdpw(context)) { + if (pw->lengths[iuid] && (int)uid == atoi(pw->starts[iuid])) { + clpw(context); return 1; } } - clpw(); + clpw(context); } return 0; } -int pw_get_uid(const char *name, uid_t *uid) +int pw_get_uid(struct tzplatform_context *context, const char *name, uid_t *uid) { - int result = oppw(); + int result = oppw(context); if (result == 0) { - while (rdpw()) { + while (rdpw(context)) { if (is(name, iname)) { - *uid = (uid_t)atoi(starts[iuid]); - clpw(); + *uid = (uid_t)atoi(context->pw.starts[iuid]); + clpw(context); return 0; } } - clpw(); + clpw(context); result = -1; errno = EEXIST; } return result; } -int pw_get_gid(const char *name, gid_t *gid) +int pw_get_gid(struct tzplatform_context *context, const char *name, gid_t *gid) { - int result = oppw(); + int result = oppw(context); if (result == 0) { - while (rdpw()) { + while (rdpw(context)) { if (is(name, iname)) { - *gid = (gid_t)atoi(starts[igid]); - clpw(); + *gid = (gid_t)atoi(context->pw.starts[igid]); + clpw(context); return 0; } } - clpw(); + clpw(context); result = -1; errno = EEXIST; } diff --git a/src/passwd.h b/src/passwd.h index 475ee10..cd3d4e6 100644 --- a/src/passwd.h +++ b/src/passwd.h @@ -24,6 +24,8 @@ #ifndef TIZEN_PLATFORM_WRAPPER_PASSWD_H #define TIZEN_PLATFORM_WRAPPER_PASSWD_H +#include "context.h" + struct pwget { int set; const char *id; @@ -31,10 +33,10 @@ struct pwget { size_t home; }; -int pw_get(struct heap *heap, struct pwget **items); -int pw_get_uid(const char *name, uid_t *uid); -int pw_get_gid(const char *name, gid_t *gid); -int pw_has_uid(uid_t uid); +int pw_get(struct tzplatform_context *context, struct heap *heap, struct pwget **items); +int pw_get_uid(struct tzplatform_context *context, const char *name, uid_t *uid); +int pw_get_gid(struct tzplatform_context *context, const char *name, gid_t *gid); +int pw_has_uid(struct tzplatform_context *context, uid_t uid); #endif diff --git a/src/shared-api.c b/src/shared-api.c index 9688d8b..8997349 100644 --- a/src/shared-api.c +++ b/src/shared-api.c @@ -42,13 +42,11 @@ #include "heap.h" #include "scratch.h" #include "passwd.h" -#include "foreign.h" #include "context.h" #include "hashing.h" #include "init.h" #include "shared-api.h" - /* the global context */ static struct tzplatform_context global_context = { #ifndef NOT_MULTI_THREAD_SAFE @@ -185,7 +183,7 @@ int tzplatform_context_set_user(struct tzplatform_context *context, uid_t uid) { lock(context); if (context->user != uid) { - if (uid != _USER_NOT_SET_ && !pw_has_uid(uid)) { + if (uid != _USER_NOT_SET_ && !pw_has_uid(context, uid)) { unlock(context); return -1; } @@ -358,7 +356,7 @@ uid_t _context_getuid_tzplatform_(int id, char signup[33], struct tzplatform_con result = (uid_t)-1; value = get_lock(id, context); if (value != NULL) - pw_get_uid(value, &result); + pw_get_uid(context, value, &result); unlock(context); return result; @@ -378,7 +376,7 @@ gid_t _context_getgid_tzplatform_(int id, char signup[33], struct tzplatform_con result = (uid_t)-1; value = get_lock(id, context); if (value != NULL) - pw_get_gid(value, &result); + pw_get_gid(context, value, &result); unlock(context); return result; -- 2.7.4