From: Lennart Poettering Date: Fri, 8 Sep 2017 14:16:29 +0000 (+0200) Subject: util-lib: wrap personality() to fix up broken glibc error handling (#6766) X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=bd4dae01104127b8b92410ea8a126d8d8d0dfcf2;p=elogind.git util-lib: wrap personality() to fix up broken glibc error handling (#6766) glibc appears to propagate different errors in different ways, let's fix this up, so that our own code doesn't get confused by this. See #6752 + #6737 for details. Fixes: #6755 --- diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 98f5a38ae..06675427e 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -913,6 +913,28 @@ const char* personality_to_string(unsigned long p) { return architecture_to_string(architecture); } +int safe_personality(unsigned long p) { + int ret; + + /* So here's the deal, personality() is weirdly defined by glibc. In some cases it returns a failure via errno, + * and in others as negative return value containing an errno-like value. Let's work around this: this is a + * wrapper that uses errno if it is set, and uses the return value otherwise. And then it sets both errno and + * the return value indicating the same issue, so that we are definitely on the safe side. + * + * See https://github.com/elogind/elogind/issues/6737 */ + + errno = 0; + ret = personality(p); + if (ret < 0) { + if (errno != 0) + return -errno; + + errno = -ret; + } + + return ret; +} + int opinionated_personality(unsigned long *ret) { int current; @@ -920,9 +942,9 @@ int opinionated_personality(unsigned long *ret) { * opinionated though, and ignores all the finer-grained bits and exotic personalities, only distinguishing the * two most relevant personalities: PER_LINUX and PER_LINUX32. */ - current = personality(PERSONALITY_INVALID); + current = safe_personality(PERSONALITY_INVALID); if (current < 0) - return -errno; + return current; if (((unsigned long) current & 0xffff) == PER_LINUX32) *ret = PER_LINUX32; diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 339dc9f59..71b473232 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -100,6 +100,7 @@ bool oom_score_adjust_is_valid(int oa); unsigned long personality_from_string(const char *p); const char *personality_to_string(unsigned long); +int safe_personality(unsigned long p); int opinionated_personality(unsigned long *ret); int ioprio_class_to_string_alloc(int i, char **s);