浏览代码

dlm: verify that places expecting rcom_lock have packet long enough

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: David Teigland <teigland@redhat.com>
Al Viro 17 年之前
父节点
当前提交
ae773d0b74
共有 2 个文件被更改,包括 14 次插入1 次删除
  1. 3 0
      fs/dlm/lock.c
  2. 11 1
      fs/dlm/rcom.c

+ 3 - 0
fs/dlm/lock.c

@@ -4266,6 +4266,7 @@ static struct dlm_lkb *search_remid(struct dlm_rsb *r, int nodeid,
 	return NULL;
 	return NULL;
 }
 }
 
 
+/* needs at least dlm_rcom + rcom_lock */
 static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
 static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
 				  struct dlm_rsb *r, struct dlm_rcom *rc)
 				  struct dlm_rsb *r, struct dlm_rcom *rc)
 {
 {
@@ -4315,6 +4316,7 @@ static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
    the given values and send back our lkid.  We send back our lkid by sending
    the given values and send back our lkid.  We send back our lkid by sending
    back the rcom_lock struct we got but with the remid field filled in. */
    back the rcom_lock struct we got but with the remid field filled in. */
 
 
+/* needs at least dlm_rcom + rcom_lock */
 int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
 int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
 {
 {
 	struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf;
 	struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf;
@@ -4370,6 +4372,7 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
 	return error;
 	return error;
 }
 }
 
 
+/* needs at least dlm_rcom + rcom_lock */
 int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
 int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
 {
 {
 	struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf;
 	struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf;

+ 11 - 1
fs/dlm/rcom.c

@@ -357,6 +357,7 @@ int dlm_send_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
 	return error;
 	return error;
 }
 }
 
 
+/* needs at least dlm_rcom + rcom_lock */
 static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in)
 static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in)
 {
 {
 	struct dlm_rcom *rc;
 	struct dlm_rcom *rc;
@@ -448,6 +449,8 @@ static int is_old_reply(struct dlm_ls *ls, struct dlm_rcom *rc)
 
 
 void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
 void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
 {
 {
+	int lock_size = sizeof(struct dlm_rcom) + sizeof(struct rcom_lock);
+
 	if (dlm_recovery_stopped(ls) && (rc->rc_type != DLM_RCOM_STATUS)) {
 	if (dlm_recovery_stopped(ls) && (rc->rc_type != DLM_RCOM_STATUS)) {
 		log_debug(ls, "ignoring recovery message %x from %d",
 		log_debug(ls, "ignoring recovery message %x from %d",
 			  rc->rc_type, nodeid);
 			  rc->rc_type, nodeid);
@@ -471,6 +474,8 @@ void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
 		break;
 		break;
 
 
 	case DLM_RCOM_LOCK:
 	case DLM_RCOM_LOCK:
+		if (rc->rc_header.h_length < lock_size)
+			goto Eshort;
 		receive_rcom_lock(ls, rc);
 		receive_rcom_lock(ls, rc);
 		break;
 		break;
 
 
@@ -487,13 +492,18 @@ void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
 		break;
 		break;
 
 
 	case DLM_RCOM_LOCK_REPLY:
 	case DLM_RCOM_LOCK_REPLY:
+		if (rc->rc_header.h_length < lock_size)
+			goto Eshort;
 		dlm_recover_process_copy(ls, rc);
 		dlm_recover_process_copy(ls, rc);
 		break;
 		break;
 
 
 	default:
 	default:
 		log_error(ls, "receive_rcom bad type %d", rc->rc_type);
 		log_error(ls, "receive_rcom bad type %d", rc->rc_type);
 	}
 	}
- out:
+out:
 	return;
 	return;
+Eshort:
+	log_error(ls, "recovery message %x from %d is too short",
+			  rc->rc_type, nodeid);
 }
 }