|
Lines 116-128
dso_name_valid_for_suid (const char *p)
Link Here
|
| 116 |
return *p != '\0'; |
116 |
return *p != '\0'; |
| 117 |
} |
117 |
} |
| 118 |
|
118 |
|
| 119 |
/* List of auditing DSOs. */ |
119 |
/* LD_AUDIT variable contents. Must be processed before the |
|
|
120 |
audit_list below. */ |
| 121 |
const char *audit_list_string; |
| 122 |
|
| 123 |
/* Cyclic list of auditing DSOs. audit_list->next is the first |
| 124 |
element. */ |
| 120 |
static struct audit_list |
125 |
static struct audit_list |
| 121 |
{ |
126 |
{ |
| 122 |
const char *name; |
127 |
const char *name; |
| 123 |
struct audit_list *next; |
128 |
struct audit_list *next; |
| 124 |
} *audit_list; |
129 |
} *audit_list; |
| 125 |
|
130 |
|
|
|
131 |
/* Iterator for audit_list_string followed by audit_list. */ |
| 132 |
struct audit_list_iter |
| 133 |
{ |
| 134 |
/* Tail of audit_list_string still needing processing, or NULL. */ |
| 135 |
const char *audit_list_tail; |
| 136 |
|
| 137 |
/* The list element returned in the previous iteration. NULL before |
| 138 |
the first element. */ |
| 139 |
struct audit_list *previous; |
| 140 |
|
| 141 |
/* Scratch buffer for returning a name which is part of |
| 142 |
audit_list_string. */ |
| 143 |
char fname[PATH_MAX]; |
| 144 |
}; |
| 145 |
|
| 146 |
/* Initialize an audit list iterator. */ |
| 147 |
static void |
| 148 |
audit_list_iter_init (struct audit_list_iter *iter) |
| 149 |
{ |
| 150 |
iter->audit_list_tail = audit_list_string; |
| 151 |
iter->previous = NULL; |
| 152 |
} |
| 153 |
|
| 154 |
/* Iterate through both audit_list_string and audit_list. */ |
| 155 |
static const char * |
| 156 |
audit_list_iter_next (struct audit_list_iter *iter) |
| 157 |
{ |
| 158 |
if (iter->audit_list_tail != NULL) |
| 159 |
{ |
| 160 |
/* First iterate over audit_list_string. */ |
| 161 |
while (*iter->audit_list_tail != '\0') |
| 162 |
{ |
| 163 |
/* Split audit list at colon. */ |
| 164 |
size_t len = strcspn (iter->audit_list_tail, ":"); |
| 165 |
if (len > 0 && len < PATH_MAX) |
| 166 |
{ |
| 167 |
memcpy (iter->fname, iter->audit_list_tail, len); |
| 168 |
iter->fname[len] = '\0'; |
| 169 |
} |
| 170 |
else |
| 171 |
/* Do not return this name to the caller. */ |
| 172 |
iter->fname[0] = '\0'; |
| 173 |
|
| 174 |
/* Skip over the substring and the following delimiter. */ |
| 175 |
iter->audit_list_tail += len; |
| 176 |
if (*iter->audit_list_tail == ':') |
| 177 |
++iter->audit_list_tail; |
| 178 |
|
| 179 |
/* If the name is valid, return it. */ |
| 180 |
if (dso_name_valid_for_suid (iter->fname)) |
| 181 |
return iter->fname; |
| 182 |
/* Otherwise, wrap around and try the next name. */ |
| 183 |
} |
| 184 |
/* Fall through to the procesing of audit_list. */ |
| 185 |
} |
| 186 |
|
| 187 |
if (iter->previous == NULL) |
| 188 |
{ |
| 189 |
if (audit_list == NULL) |
| 190 |
/* No pre-parsed audit list. */ |
| 191 |
return NULL; |
| 192 |
/* Start of audit list. The first list element is at |
| 193 |
audit_list->next (cyclic list). */ |
| 194 |
iter->previous = audit_list->next; |
| 195 |
return iter->previous->name; |
| 196 |
} |
| 197 |
if (iter->previous == audit_list) |
| 198 |
/* Cyclic list wrap-around. */ |
| 199 |
return NULL; |
| 200 |
iter->previous = iter->previous->next; |
| 201 |
return iter->previous->name; |
| 202 |
} |
| 203 |
|
| 126 |
#ifndef HAVE_INLINED_SYSCALLS |
204 |
#ifndef HAVE_INLINED_SYSCALLS |
| 127 |
/* Set nonzero during loading and initialization of executable and |
205 |
/* Set nonzero during loading and initialization of executable and |
| 128 |
libraries, cleared before the executable's entry point runs. This |
206 |
libraries, cleared before the executable's entry point runs. This |
|
Lines 1290-1300
of this helper program; chances are you did not intend to run this program.\n\
Link Here
|
| 1290 |
GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid (); |
1368 |
GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid (); |
| 1291 |
|
1369 |
|
| 1292 |
/* If we have auditing DSOs to load, do it now. */ |
1370 |
/* If we have auditing DSOs to load, do it now. */ |
| 1293 |
if (__glibc_unlikely (audit_list != NULL)) |
1371 |
bool need_security_init = true; |
|
|
1372 |
if (__glibc_unlikely (audit_list != NULL) |
| 1373 |
|| __glibc_unlikely (audit_list_string != NULL)) |
| 1294 |
{ |
1374 |
{ |
| 1295 |
/* Iterate over all entries in the list. The order is important. */ |
|
|
| 1296 |
struct audit_ifaces *last_audit = NULL; |
1375 |
struct audit_ifaces *last_audit = NULL; |
| 1297 |
struct audit_list *al = audit_list->next; |
1376 |
struct audit_list_iter al_iter; |
|
|
1377 |
audit_list_iter_init (&al_iter); |
| 1298 |
|
1378 |
|
| 1299 |
/* Since we start using the auditing DSOs right away we need to |
1379 |
/* Since we start using the auditing DSOs right away we need to |
| 1300 |
initialize the data structures now. */ |
1380 |
initialize the data structures now. */ |
|
Lines 1305-1313
of this helper program; chances are you did not intend to run this program.\n\
Link Here
|
| 1305 |
use different values (especially the pointer guard) and will |
1385 |
use different values (especially the pointer guard) and will |
| 1306 |
fail later on. */ |
1386 |
fail later on. */ |
| 1307 |
security_init (); |
1387 |
security_init (); |
|
|
1388 |
need_security_init = false; |
| 1308 |
|
1389 |
|
| 1309 |
do |
1390 |
while (true) |
| 1310 |
{ |
1391 |
{ |
|
|
1392 |
const char *name = audit_list_iter_next (&al_iter); |
| 1393 |
if (name == NULL) |
| 1394 |
break; |
| 1395 |
|
| 1311 |
int tls_idx = GL(dl_tls_max_dtv_idx); |
1396 |
int tls_idx = GL(dl_tls_max_dtv_idx); |
| 1312 |
|
1397 |
|
| 1313 |
/* Now it is time to determine the layout of the static TLS |
1398 |
/* Now it is time to determine the layout of the static TLS |
|
Lines 1316-1322
of this helper program; chances are you did not intend to run this program.\n\
Link Here
|
| 1316 |
no DF_STATIC_TLS bit is set. The reason is that we know |
1401 |
no DF_STATIC_TLS bit is set. The reason is that we know |
| 1317 |
glibc will use the static model. */ |
1402 |
glibc will use the static model. */ |
| 1318 |
struct dlmopen_args dlmargs; |
1403 |
struct dlmopen_args dlmargs; |
| 1319 |
dlmargs.fname = al->name; |
1404 |
dlmargs.fname = name; |
| 1320 |
dlmargs.map = NULL; |
1405 |
dlmargs.map = NULL; |
| 1321 |
|
1406 |
|
| 1322 |
const char *objname; |
1407 |
const char *objname; |
|
Lines 1329-1335
of this helper program; chances are you did not intend to run this program.\n\
Link Here
|
| 1329 |
not_loaded: |
1414 |
not_loaded: |
| 1330 |
_dl_error_printf ("\ |
1415 |
_dl_error_printf ("\ |
| 1331 |
ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", |
1416 |
ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", |
| 1332 |
al->name, err_str); |
1417 |
name, err_str); |
| 1333 |
if (malloced) |
1418 |
if (malloced) |
| 1334 |
free ((char *) err_str); |
1419 |
free ((char *) err_str); |
| 1335 |
} |
1420 |
} |
|
Lines 1433-1442
ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
Link Here
|
| 1433 |
goto not_loaded; |
1518 |
goto not_loaded; |
| 1434 |
} |
1519 |
} |
| 1435 |
} |
1520 |
} |
| 1436 |
|
|
|
| 1437 |
al = al->next; |
| 1438 |
} |
1521 |
} |
| 1439 |
while (al != audit_list->next); |
|
|
| 1440 |
|
1522 |
|
| 1441 |
/* If we have any auditing modules, announce that we already |
1523 |
/* If we have any auditing modules, announce that we already |
| 1442 |
have two objects loaded. */ |
1524 |
have two objects loaded. */ |
|
Lines 1700-1706
ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
Link Here
|
| 1700 |
if (tcbp == NULL) |
1782 |
if (tcbp == NULL) |
| 1701 |
tcbp = init_tls (); |
1783 |
tcbp = init_tls (); |
| 1702 |
|
1784 |
|
| 1703 |
if (__glibc_likely (audit_list == NULL)) |
1785 |
if (__glibc_likely (need_security_init)) |
| 1704 |
/* Initialize security features. But only if we have not done it |
1786 |
/* Initialize security features. But only if we have not done it |
| 1705 |
earlier. */ |
1787 |
earlier. */ |
| 1706 |
security_init (); |
1788 |
security_init (); |
|
Lines 2331-2339
process_dl_audit (char *str)
Link Here
|
| 2331 |
char *p; |
2413 |
char *p; |
| 2332 |
|
2414 |
|
| 2333 |
while ((p = (strsep) (&str, ":")) != NULL) |
2415 |
while ((p = (strsep) (&str, ":")) != NULL) |
| 2334 |
if (p[0] != '\0' |
2416 |
if (dso_name_valid_for_suid (p)) |
| 2335 |
&& (__builtin_expect (! __libc_enable_secure, 1) |
|
|
| 2336 |
|| strchr (p, '/') == NULL)) |
| 2337 |
{ |
2417 |
{ |
| 2338 |
/* This is using the local malloc, not the system malloc. The |
2418 |
/* This is using the local malloc, not the system malloc. The |
| 2339 |
memory can never be freed. */ |
2419 |
memory can never be freed. */ |
|
Lines 2397-2403
process_envvars (enum mode *modep)
Link Here
|
| 2397 |
break; |
2477 |
break; |
| 2398 |
} |
2478 |
} |
| 2399 |
if (memcmp (envline, "AUDIT", 5) == 0) |
2479 |
if (memcmp (envline, "AUDIT", 5) == 0) |
| 2400 |
process_dl_audit (&envline[6]); |
2480 |
audit_list_string = &envline[6]; |
| 2401 |
break; |
2481 |
break; |
| 2402 |
|
2482 |
|
| 2403 |
case 7: |
2483 |
case 7: |
| 2404 |
- |
|
|