staticinlinebool atomic_long_inc_below(atomic_long_t *v, long u)
{ long c = atomic_long_read(v);
do { if (unlikely(c >= u)) returnfalse;
} while (!atomic_long_try_cmpxchg(v, &c, c+1));
returntrue;
}
struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid, enum ucount_type type)
{ struct ucounts *ucounts, *iter, *bad; struct user_namespace *tns;
ucounts = alloc_ucounts(ns, uid); for (iter = ucounts; iter; iter = tns->ucounts) { long max;
tns = iter->ns;
max = READ_ONCE(tns->ucount_max[type]); if (!atomic_long_inc_below(&iter->ucount[type], max)) goto fail;
} return ucounts;
fail:
bad = iter; for (iter = ucounts; iter != bad; iter = iter->ns->ucounts)
atomic_long_dec(&iter->ucount[type]);
put_ucounts(ucounts); return NULL;
}
void dec_ucount(struct ucounts *ucounts, enum ucount_type type)
{ struct ucounts *iter; for (iter = ucounts; iter; iter = iter->ns->ucounts) { long dec = atomic_long_dec_if_positive(&iter->ucount[type]);
WARN_ON_ONCE(dec < 0);
}
put_ucounts(ucounts);
}
long inc_rlimit_ucounts(struct ucounts *ucounts, enum rlimit_type type, long v)
{ struct ucounts *iter; long max = LONG_MAX; long ret = 0;
for (iter = ucounts; iter; iter = iter->ns->ucounts) { longnew = atomic_long_add_return(v, &iter->rlimit[type]); if (new < 0 || new > max)
ret = LONG_MAX; elseif (iter == ucounts)
ret = new;
max = get_userns_rlimit_max(iter->ns, type);
} return ret;
}
bool dec_rlimit_ucounts(struct ucounts *ucounts, enum rlimit_type type, long v)
{ struct ucounts *iter; longnew = -1; /* Silence compiler warning */ for (iter = ucounts; iter; iter = iter->ns->ucounts) { long dec = atomic_long_sub_return(v, &iter->rlimit[type]);
WARN_ON_ONCE(dec < 0); if (iter == ucounts) new = dec;
} return (new == 0);
}
staticvoid do_dec_rlimit_put_ucounts(struct ucounts *ucounts, struct ucounts *last, enum rlimit_type type)
{ struct ucounts *iter, *next; for (iter = ucounts; iter != last; iter = next) { long dec = atomic_long_sub_return(1, &iter->rlimit[type]);
WARN_ON_ONCE(dec < 0);
next = iter->ns->ucounts; if (dec == 0)
put_ucounts(iter);
}
}
long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum rlimit_type type, bool override_rlimit)
{ /* Caller must hold a reference to ucounts */ struct ucounts *iter; long max = LONG_MAX; long dec, ret = 0;
for (iter = ucounts; iter; iter = iter->ns->ucounts) { longnew = atomic_long_add_return(1, &iter->rlimit[type]); if (new < 0 || new > max) goto dec_unwind; if (iter == ucounts)
ret = new; if (!override_rlimit)
max = get_userns_rlimit_max(iter->ns, type); /* * Grab an extra ucount reference for the caller when * the rlimit count was previously 0.
*/ if (new != 1) continue; if (!get_ucounts(iter)) goto dec_unwind;
} return ret;
dec_unwind:
dec = atomic_long_sub_return(1, &iter->rlimit[type]);
WARN_ON_ONCE(dec < 0);
do_dec_rlimit_put_ucounts(ucounts, iter, type); return 0;
}
bool is_rlimit_overlimit(struct ucounts *ucounts, enum rlimit_type type, unsignedlong rlimit)
{ struct ucounts *iter; long max = rlimit; if (rlimit > LONG_MAX)
max = LONG_MAX; for (iter = ucounts; iter; iter = iter->ns->ucounts) { long val = get_rlimit_value(iter, type); if (val < 0 || val > max) returntrue;
max = get_userns_rlimit_max(iter->ns, type);
} returnfalse;
}
static __init int user_namespace_sysctl_init(void)
{ #ifdef CONFIG_SYSCTL staticstruct ctl_table_header *user_header; staticstruct ctl_table empty[1]; /* * It is necessary to register the user directory in the * default set so that registrations in the child sets work * properly.
*/
user_header = register_sysctl_sz("user", empty, 0);
kmemleak_ignore(user_header);
BUG_ON(!user_header);
BUG_ON(!setup_userns_sysctls(&init_user_ns)); #endif
hlist_add_ucounts(&init_ucounts);
inc_rlimit_ucounts(&init_ucounts, UCOUNT_RLIMIT_NPROC, 1); return 0;
}
subsys_initcall(user_namespace_sysctl_init);
Messung V0.5
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.