浏览代码

Merge tag 'random_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random

Pull /dev/random fix from Ted Ts'o:
 "Fix a BUG splat found by trinity"

* tag 'random_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random:
  random: check for increase of entropy_count because of signed conversion
Linus Torvalds 11 年之前
父节点
当前提交
b8d2d12804
共有 1 个文件被更改,包括 14 次插入3 次删除
  1. 14 3
      drivers/char/random.c

+ 14 - 3
drivers/char/random.c

@@ -641,7 +641,7 @@ retry:
 		} while (unlikely(entropy_count < pool_size-2 && pnfrac));
 		} while (unlikely(entropy_count < pool_size-2 && pnfrac));
 	}
 	}
 
 
-	if (entropy_count < 0) {
+	if (unlikely(entropy_count < 0)) {
 		pr_warn("random: negative entropy/overflow: pool %s count %d\n",
 		pr_warn("random: negative entropy/overflow: pool %s count %d\n",
 			r->name, entropy_count);
 			r->name, entropy_count);
 		WARN_ON(1);
 		WARN_ON(1);
@@ -981,7 +981,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
 		      int reserved)
 		      int reserved)
 {
 {
 	int entropy_count, orig;
 	int entropy_count, orig;
-	size_t ibytes;
+	size_t ibytes, nfrac;
 
 
 	BUG_ON(r->entropy_count > r->poolinfo->poolfracbits);
 	BUG_ON(r->entropy_count > r->poolinfo->poolfracbits);
 
 
@@ -999,7 +999,17 @@ retry:
 	}
 	}
 	if (ibytes < min)
 	if (ibytes < min)
 		ibytes = 0;
 		ibytes = 0;
-	if ((entropy_count -= ibytes << (ENTROPY_SHIFT + 3)) < 0)
+
+	if (unlikely(entropy_count < 0)) {
+		pr_warn("random: negative entropy count: pool %s count %d\n",
+			r->name, entropy_count);
+		WARN_ON(1);
+		entropy_count = 0;
+	}
+	nfrac = ibytes << (ENTROPY_SHIFT + 3);
+	if ((size_t) entropy_count > nfrac)
+		entropy_count -= nfrac;
+	else
 		entropy_count = 0;
 		entropy_count = 0;
 
 
 	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
 	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
@@ -1376,6 +1386,7 @@ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 			    "with %d bits of entropy available\n",
 			    "with %d bits of entropy available\n",
 			    current->comm, nonblocking_pool.entropy_total);
 			    current->comm, nonblocking_pool.entropy_total);
 
 
+	nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
 	ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);
 	ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);
 
 
 	trace_urandom_read(8 * nbytes, ENTROPY_BITS(&nonblocking_pool),
 	trace_urandom_read(8 * nbytes, ENTROPY_BITS(&nonblocking_pool),