dlm: some checks can underflow
Subsystems (2)
PATCH 1/1 dlm: some checks can underflow
This is a static checker fix. We have several places here that check the upper limit without checking for negative numbers. One example of this is in find_rsb().
My static checker marks endian data as user controled so. The "ms->m_header.h_length" variable is tagged as user data because it starts as little endian and we convert it at the start of dlm_receive_buffer(). That means that receive_extralen() returns user controlled data which could be negative. The call tree here is:
-> dlm_receive_buffer()
-> dlm_receive_message()
-> _receive_message()
-> receive_request()
We get "namelen" from receive_extralen(ms);
-> find_rsb()It's never perfectly clear how invasive to make a fix like this. Many of the changes in the patch are not needed but I wanted to make things consistent.
---
Compile tested only.
fs/dlm/lock.h +5 -4
@@ -14,7 +14,7 @@#define __LOCK_DOT_H__void dlm_dump_rsb (struct dlm_rsb *r); -void dlm_dump_rsb_name (struct dlm_ls *ls,char *name,int len); +void dlm_dump_rsb_name (struct dlm_ls *ls,char *name,unsigned int len);void dlm_print_lkb (struct dlm_lkb *lkb);void dlm_receive_message_saved (struct dlm_ls *ls,struct dlm_message *ms,uint32_t saved_seq);
@@ -29,10 +29,11 @@ void dlm_unlock_recovery(struct dlm_ls *ls);void dlm_scan_waiters (struct dlm_ls *ls);void dlm_scan_timeout (struct dlm_ls *ls);void dlm_adjust_timeouts (struct dlm_ls *ls); -int dlm_master_lookup (struct dlm_ls *ls,int nodeid,char *name,int len, -unsigned int flags,int *r_nodeid,int *result); +int dlm_master_lookup (struct dlm_ls *ls,int nodeid,char *name, +unsigned int len,unsigned int flags,int *r_nodeid, +int *result); -int dlm_search_rsb_tree (struct rb_root *tree,char *name,int len, +int dlm_search_rsb_tree (struct rb_root *tree,char *name,unsigned int len,struct dlm_rsb **r_ret);void dlm_recover_purge (struct dlm_ls *ls);
fs/dlm/lock.c +30 -23
173 lines not on this page · raw message
David Teigland
maintainerPATCH 1/1 dlm: some checks can underflow
Quoted 19 lines · Dan Carpenter
This is a static checker fix. We have several places here that check the upper limit without checking for negative numbers. One example of this is in
find_rsb().My static checker marks endian data as user controled so. The "
ms->m_header.h_length" variable is tagged as user data because it starts as little endian and we convert it at the start ofdlm_receive_buffer(). That means thatreceive_extralen()returns user controlled data which could be negative. The call tree here is:->
dlm_receive_buffer()
->dlm_receive_message()-> _receive_message() -> receive_request() We get "namelen" from receive_extralen(ms); -> find_rsb()
Quoted 3 lines
It's never perfectly clear how invasive to make a fix like this. Many of the changes in the patch are not needed but I wanted to make things consistent.
If it's negative, I don't think it would pass the h_length validation in dlm_process_incoming_buffer(), but I'm not certain...
fs/dlm/lock.c static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, · line 5603
Quoted 6 lines
fs/dlm/lock.c +2
-2-int lvblen = rc->rc_header.h_length -sizeof (struct dlm_rcom ) - -sizeof (struct rcom_lock ); +unsigned int lvblen = rc->rc_header.h_length - +sizeof (struct dlm_rcom ) -sizeof (struct rcom_lock );if (lvblen > ls->ls_lvblen)return -EINVAL ;
Easier to just change that check to
if (lvblen != ls->ls_lvblen)
return -EINVAL;
Dave
PATCH 1/1 dlm: some checks can underflow
Quoted 18 lines · David Teigland
Quoted 17 lines · Dan Carpenter
This is a static checker fix. We have several places here that check the upper limit without checking for negative numbers. One example of this is in
find_rsb().My static checker marks endian data as user controled so. The "
ms->m_header.h_length" variable is tagged as user data because it starts as little endian and we convert it at the start ofdlm_receive_buffer(). That means thatreceive_extralen()returns user controlled data which could be negative. The call tree here is:->
dlm_receive_buffer()
->dlm_receive_message()-> _receive_message() -> receive_request() We get "namelen" from receive_extralen(ms);
Quoted 8 lines
Quoted 5 lines
-> find_rsb()It's never perfectly clear how invasive to make a fix like this. Many of the changes in the patch are not needed but I wanted to make things consistent.
If it's negative, I don't think it would pass the
h_lengthvalidation indlm_process_incoming_buffer(), but I'm not certain...
Gar, yeah. We check that:
if (p->header.h_cmd == DLM_MSG) {
if (msglen < sizeof(struct dlm_message))
break;Which means receive_extralen() can't return negative.
We can drop this patch.
regards,
dan carpenter