On Sat, Jan 12, 2019 at 7:28 AM Willy Tarreau <[email protected]> wrote: > > From: Silvio Cesare <[email protected]> > > Change snprintf to scnprintf. There are generally two cases where using > snprintf causes problems. > > 1) Uses of size += snprintf(buf, SIZE - size, fmt, ...) > In this case, if snprintf would have written more characters than what the > buffer size (SIZE) is, then size will end up larger than SIZE. In later > uses of snprintf, SIZE - size will result in a negative number, leading > to problems. Note that size might already be too large by using > size = snprintf before the code reaches a case of size += snprintf. > > 2) If size is ultimately used as a length parameter for a copy back to user > space, then it will potentially allow for a buffer overflow and information > disclosure when size is greater than SIZE. When the size is used to index > the buffer directly, we can have memory corruption. This also means when > size = snprintf... is used, it may also cause problems since size may become > large. Copying to userspace is mitigated by the HARDENED_USERCOPY kernel > configuration. > > The solution to these issues is to use scnprintf which returns the number of > characters actually written to the buffer, so the size variable will never > exceed SIZE. > > Signed-off-by: Silvio Cesare <[email protected]> > Cc: Mark Fasheh <[email protected]> > Cc: Joel Becker <[email protected]> > Cc: Dan Carpenter <[email protected]> > Cc: Kees Cook <[email protected]> > Cc: Will Deacon <[email protected]> > Cc: Greg KH <[email protected]> > Signed-off-by: Willy Tarreau <[email protected]>
Reviewed-by: Kees Cook <[email protected]> -Kees > > --- > fs/ocfs2/cluster/heartbeat.c | 10 +++++----- > 1 file changed, 5 insertions(+), 5 deletions(-) > > diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c > index 9b2ed62dd638..2a0af0887ba0 100644 > --- a/fs/ocfs2/cluster/heartbeat.c > +++ b/fs/ocfs2/cluster/heartbeat.c > @@ -1324,7 +1324,7 @@ static int o2hb_debug_open(struct inode *inode, struct > file *file) > > case O2HB_DB_TYPE_REGION_NUMBER: > reg = (struct o2hb_region *)db->db_data; > - out += snprintf(buf + out, PAGE_SIZE - out, "%d\n", > + out += scnprintf(buf + out, PAGE_SIZE - out, "%d\n", > reg->hr_region_num); > goto done; > > @@ -1334,12 +1334,12 @@ static int o2hb_debug_open(struct inode *inode, > struct file *file) > /* If 0, it has never been set before */ > if (lts) > lts = jiffies_to_msecs(jiffies - lts); > - out += snprintf(buf + out, PAGE_SIZE - out, "%lu\n", lts); > + out += scnprintf(buf + out, PAGE_SIZE - out, "%lu\n", lts); > goto done; > > case O2HB_DB_TYPE_REGION_PINNED: > reg = (struct o2hb_region *)db->db_data; > - out += snprintf(buf + out, PAGE_SIZE - out, "%u\n", > + out += scnprintf(buf + out, PAGE_SIZE - out, "%u\n", > !!reg->hr_item_pinned); > goto done; > > @@ -1348,8 +1348,8 @@ static int o2hb_debug_open(struct inode *inode, struct > file *file) > } > > while ((i = find_next_bit(map, db->db_len, i + 1)) < db->db_len) > - out += snprintf(buf + out, PAGE_SIZE - out, "%d ", i); > - out += snprintf(buf + out, PAGE_SIZE - out, "\n"); > + out += scnprintf(buf + out, PAGE_SIZE - out, "%d ", i); > + out += scnprintf(buf + out, PAGE_SIZE - out, "\n"); > > done: > i_size_write(inode, out); > -- > 2.19.2 > -- Kees Cook

