ANDROID: fix overflow in /proc/uid_cputime/remove_uid_range
Writing large values to remove_uid_range can cause an overflow & system hang. To prevent this, read in the start and end of the range using kstrtouint to ensure the full range can fit in a uid_t, and use a u64 for our loop counters to avoid overflow when the range ends at UINT_MAX. Test: "echo '9223372036854775807-9223372036854775807' > \ /proc/uid_cputime/remove_uid_range" now returns error instead of hanging Bug: 139902843 Signed-off-by: Connor O'Brien <connoro@google.com> Change-Id: I30138f95a1c56366a79eec27bbc476c9ea5773ae
This commit is contained in:
parent
c9083aa80b
commit
0adcd7cfd0
2 changed files with 11 additions and 9 deletions
|
@ -523,13 +523,14 @@ void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end)
|
|||
struct uid_entry *uid_entry;
|
||||
struct hlist_node *tmp;
|
||||
unsigned long flags;
|
||||
u64 uid;
|
||||
|
||||
spin_lock_irqsave(&uid_lock, flags);
|
||||
|
||||
for (; uid_start <= uid_end; uid_start++) {
|
||||
for (uid = uid_start; uid <= uid_end; uid++) {
|
||||
hash_for_each_possible_safe(uid_hash_table, uid_entry, tmp,
|
||||
hash, uid_start) {
|
||||
if (uid_start == uid_entry->uid) {
|
||||
hash, uid) {
|
||||
if (uid == uid_entry->uid) {
|
||||
hash_del_rcu(&uid_entry->hash);
|
||||
call_rcu(&uid_entry->rcu, uid_entry_reclaim);
|
||||
}
|
||||
|
|
|
@ -401,7 +401,8 @@ static ssize_t uid_remove_write(struct file *file,
|
|||
struct hlist_node *tmp;
|
||||
char uids[128];
|
||||
char *start_uid, *end_uid = NULL;
|
||||
long int uid_start = 0, uid_end = 0;
|
||||
uid_t uid_start = 0, uid_end = 0;
|
||||
u64 uid;
|
||||
|
||||
if (count >= sizeof(uids))
|
||||
count = sizeof(uids) - 1;
|
||||
|
@ -416,8 +417,8 @@ static ssize_t uid_remove_write(struct file *file,
|
|||
if (!start_uid || !end_uid)
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtol(start_uid, 10, &uid_start) != 0 ||
|
||||
kstrtol(end_uid, 10, &uid_end) != 0) {
|
||||
if (kstrtouint(start_uid, 10, &uid_start) != 0 ||
|
||||
kstrtouint(end_uid, 10, &uid_end) != 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -426,10 +427,10 @@ static ssize_t uid_remove_write(struct file *file,
|
|||
|
||||
rt_mutex_lock(&uid_lock);
|
||||
|
||||
for (; uid_start <= uid_end; uid_start++) {
|
||||
for (uid = uid_start; uid <= uid_end; uid++) {
|
||||
hash_for_each_possible_safe(hash_table, uid_entry, tmp,
|
||||
hash, (uid_t)uid_start) {
|
||||
if (uid_start == uid_entry->uid) {
|
||||
hash, uid) {
|
||||
if (uid == uid_entry->uid) {
|
||||
remove_uid_tasks(uid_entry);
|
||||
hash_del(&uid_entry->hash);
|
||||
kfree(uid_entry);
|
||||
|
|
Loading…
Reference in a new issue