1 /* GLIB - Library of useful routines for C programming
2 *
3 * Copyright (C) 2020 Red Hat, Inc.
4 *
5 * Author: Jakub Jelen <jjelen@redhat.com>
6 *
7 * SPDX-License-Identifier: LGPL-2.1-or-later
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General
20 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include <dlfcn.h>
24 #include <pwd.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27
28 #ifndef __APPLE__
29
30 #define GET_REAL(func) \
31 (real_##func = dlsym (RTLD_NEXT, #func))
32
33 #define DEFINE_WRAPPER(return_type, func, argument_list) \
34 static return_type (* real_##func) argument_list; \
35 return_type func argument_list
36
37 #else
38
39 #define GET_REAL(func) \
40 func
41
42 /* https://opensource.apple.com/source/dyld/dyld-852.2/include/mach-o/dyld-interposing.h */
43 #define DYLD_INTERPOSE(_replacement,_replacee) \
44 __attribute__((used)) static struct{ const void* replacement; const void* replacee; } _interpose_##_replacee \
45 __attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacement, (const void*)(unsigned long)&_replacee };
46
47 #define DEFINE_WRAPPER(return_type, func, argument_list) \
48 static return_type wrap_##func argument_list; \
49 DYLD_INTERPOSE(wrap_##func, func) \
50 static return_type wrap_##func argument_list
51
52 #endif /* __APPLE__ */
53
54 /* This is used in gutils.c used to make sure utility functions
55 * handling user information do not crash on bad data (for example
56 * caused by getpwuid returning some NULL elements.
57 */
58
59 #undef getpwuid
60
61 static struct passwd my_pw;
62
63 DEFINE_WRAPPER (struct passwd *, getpwuid, (uid_t uid))
64 {
65 struct passwd *pw = GET_REAL (getpwuid) (uid);
66 my_pw = *pw;
67 my_pw.pw_name = NULL;
68 return &my_pw;
69 }
70
71 DEFINE_WRAPPER (int, getpwnam_r, (const char *name,
72 struct passwd *pwd,
73 char buf[],
74 size_t buflen,
75 struct passwd **result))
76 {
77 int code = GET_REAL (getpwnam_r) (name, pwd, buf, buflen, result);
78 pwd->pw_name = NULL;
79 return code;
80 }
81
82 DEFINE_WRAPPER (int, getpwuid_r, (uid_t uid,
83 struct passwd *restrict pwd,
84 char buf[],
85 size_t buflen,
86 struct passwd **result))
87 {
88 int code = GET_REAL (getpwuid_r) (uid, pwd, buf, buflen, result);
89 pwd->pw_name = NULL;
90 return code;
91 }