Skip to content

Commit fbb17b4

Browse files
Erik GillingSteve Kondik
authored andcommitted
power: wakelocks: fix buffer overflow in print_wake_locks
Change-Id: Ic944e3b3d3bc53eddc6fd0963565fd072cac373c Signed-off-by: Erik Gilling <[email protected]>
1 parent 78d4364 commit fbb17b4

File tree

1 file changed

+25
-19
lines changed

1 file changed

+25
-19
lines changed

kernel/power/wakelock.c

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
4040
#define WAKE_LOCK_AUTO_EXPIRE (1U << 10)
4141
#define WAKE_LOCK_PREVENTING_SUSPEND (1U << 11)
4242

43+
#define TOO_MAY_LOCKS_WARNING "\n\ntoo many wakelocks!!!\n"
44+
4345
static DEFINE_SPINLOCK(list_lock);
4446
static LIST_HEAD(inactive_locks);
4547
static struct list_head active_wake_locks[WAKE_LOCK_TYPE_COUNT];
@@ -81,13 +83,15 @@ int get_expired_time(struct wake_lock *lock, ktime_t *expire_time)
8183
}
8284

8385

84-
static int print_lock_stat(char *buf, struct wake_lock *lock)
86+
static int print_lock_stat(char *buf, int len, struct wake_lock *lock)
8587
{
8688
int lock_count = lock->stat.count;
8789
int expire_count = lock->stat.expire_count;
8890
ktime_t active_time = ktime_set(0, 0);
8991
ktime_t total_time = lock->stat.total_time;
9092
ktime_t max_time = lock->stat.max_time;
93+
int n;
94+
9195
ktime_t prevent_suspend_time = lock->stat.prevent_suspend_time;
9296
if (lock->flags & WAKE_LOCK_ACTIVE) {
9397
ktime_t now, add_time;
@@ -108,12 +112,15 @@ static int print_lock_stat(char *buf, struct wake_lock *lock)
108112
max_time = add_time;
109113
}
110114

111-
return sprintf(buf, "\"%s\"\t%d\t%d\t%d\t%lld\t%lld\t%lld\t%lld\t"
112-
"%lld\n", lock->name, lock_count, expire_count,
113-
lock->stat.wakeup_count, ktime_to_ns(active_time),
114-
ktime_to_ns(total_time),
115-
ktime_to_ns(prevent_suspend_time), ktime_to_ns(max_time),
116-
ktime_to_ns(lock->stat.last_time));
115+
n = snprintf(buf, len,
116+
"\"%s\"\t%d\t%d\t%d\t%lld\t%lld\t%lld\t%lld\t%lld\n",
117+
lock->name, lock_count, expire_count,
118+
lock->stat.wakeup_count, ktime_to_ns(active_time),
119+
ktime_to_ns(total_time),
120+
ktime_to_ns(prevent_suspend_time), ktime_to_ns(max_time),
121+
ktime_to_ns(lock->stat.last_time));
122+
123+
return n > len ? len : n;
117124
}
118125

119126

@@ -123,31 +130,30 @@ static int wakelocks_read_proc(char *page, char **start, off_t off,
123130
unsigned long irqflags;
124131
struct wake_lock *lock;
125132
int len = 0;
126-
char *p = page;
127133
int type;
128134

129135
spin_lock_irqsave(&list_lock, irqflags);
130136

131-
p += sprintf(p, "name\tcount\texpire_count\twake_count\tactive_since"
132-
"\ttotal_time\tsleep_time\tmax_time\tlast_change\n");
137+
len += snprintf(page + len, count - len,
138+
"name\tcount\texpire_count\twake_count\tactive_since"
139+
"\ttotal_time\tsleep_time\tmax_time\tlast_change\n");
133140
list_for_each_entry(lock, &inactive_locks, link) {
134-
p += print_lock_stat(p, lock);
141+
len += print_lock_stat(page + len, count - len, lock);
135142
}
136143
for (type = 0; type < WAKE_LOCK_TYPE_COUNT; type++) {
137144
list_for_each_entry(lock, &active_wake_locks[type], link)
138-
p += print_lock_stat(p, lock);
145+
len += print_lock_stat(page + len, count - len, lock);
139146
}
140147
spin_unlock_irqrestore(&list_lock, irqflags);
141148

142-
*start = page + off;
149+
if (len == count)
150+
memcpy(page + len - strlen(TOO_MAY_LOCKS_WARNING),
151+
TOO_MAY_LOCKS_WARNING,
152+
strlen(TOO_MAY_LOCKS_WARNING));
143153

144-
len = p - page;
145-
if (len > off)
146-
len -= off;
147-
else
148-
len = 0;
154+
*eof = 1;
149155

150-
return len < count ? len : count;
156+
return len;
151157
}
152158

153159
static void wake_unlock_stat_locked(struct wake_lock *lock, int expired)

0 commit comments

Comments
 (0)