KEYS: trusted: fix writing past end of buffer in trusted_read()
[sfrench/cifs-2.6.git] / security / keys / trusted.c
index bd85315cbfeb3e1bad3b01e7d9a6538bbb5d3577..98aa89ff7bfd9ed57662116ca455f3a5628ec380 100644 (file)
@@ -1147,20 +1147,21 @@ static long trusted_read(const struct key *key, char __user *buffer,
        p = dereference_key_locked(key);
        if (!p)
                return -EINVAL;
        p = dereference_key_locked(key);
        if (!p)
                return -EINVAL;
-       if (!buffer || buflen <= 0)
-               return 2 * p->blob_len;
-       ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
-       if (!ascii_buf)
-               return -ENOMEM;
 
 
-       bufp = ascii_buf;
-       for (i = 0; i < p->blob_len; i++)
-               bufp = hex_byte_pack(bufp, p->blob[i]);
-       if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) {
+       if (buffer && buflen >= 2 * p->blob_len) {
+               ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
+               if (!ascii_buf)
+                       return -ENOMEM;
+
+               bufp = ascii_buf;
+               for (i = 0; i < p->blob_len; i++)
+                       bufp = hex_byte_pack(bufp, p->blob[i]);
+               if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
+                       kzfree(ascii_buf);
+                       return -EFAULT;
+               }
                kzfree(ascii_buf);
                kzfree(ascii_buf);
-               return -EFAULT;
        }
        }
-       kzfree(ascii_buf);
        return 2 * p->blob_len;
 }
 
        return 2 * p->blob_len;
 }