@@ -3497,16 +3497,19 @@ nmreq_copyin(struct nmreq_header *hdr, int nr_body_is_user)
34973497		}
34983498		opt_tab [opt -> nro_reqtype ] =  opt ;
34993499
3500- 		/* copy the option body */ 
3501- 		optsz  =  nmreq_opt_size_by_type (opt -> nro_reqtype ,
3502- 						opt -> nro_size );
3503- 		/* check optsz and nro_size to avoid for possible integer overflows of rqsz */ 
3504- 		if  ((optsz  >  NETMAP_REQ_MAXSIZE ) ||  (opt -> nro_size  >  NETMAP_REQ_MAXSIZE )
3505- 				||  (rqsz  +  optsz  >  NETMAP_REQ_MAXSIZE )
3506- 				||  (optsz  >  0  &&  rqsz  +  optsz  <= rqsz )) {
3507- 			error  =  EMSGSIZE ;
3508- 			goto out_restore ;
3509- 		}
3500+         /* copy the option body */ 
3501+         optsz  =  nmreq_opt_size_by_type (opt -> nro_reqtype ,
3502+                         opt -> nro_size );
3503+         /* enforce exact option body size and overflow guards */ 
3504+         if  ((optsz  ==  0  &&  opt -> nro_size  !=  0 ) ||  (opt -> nro_size  !=  optsz )) {
3505+             error  =  EINVAL ;
3506+             goto out_restore ;
3507+         }
3508+         if  ((optsz  >  NETMAP_REQ_MAXSIZE ) ||  (opt -> nro_size  >  NETMAP_REQ_MAXSIZE )
3509+                 ||  (rqsz  >  NETMAP_REQ_MAXSIZE  -  optsz )) {
3510+             error  =  EMSGSIZE ;
3511+             goto out_restore ;
3512+         }
35103513		rqsz  +=  optsz ;
35113514		if  (optsz ) {
35123515			/* the option body follows the option header */ 
@@ -3584,10 +3587,15 @@ nmreq_copyout(struct nmreq_header *hdr, int rerror)
35843587			goto out ;
35853588		}
35863589
3587- 		/* copy the option body only if there was no error */ 
3588- 		if  (!rerror  &&  !src -> nro_status ) {
3589- 			optsz  =  nmreq_opt_size_by_type (src -> nro_reqtype ,
3590- 							src -> nro_size );
3590+         /* copy the option body only if there was no error */ 
3591+         if  (!rerror  &&  !src -> nro_status ) {
3592+             optsz  =  nmreq_opt_size_by_type (src -> nro_reqtype ,
3593+                             src -> nro_size );
3594+             /* enforce symmetry for copyout */ 
3595+             if  ((optsz  ==  0  &&  src -> nro_size  !=  0 ) ||  (src -> nro_size  !=  optsz )) {
3596+                 rerror  =  EINVAL ;
3597+                 goto out ;
3598+             }
35913599			if  (optsz ) {
35923600				error  =  copyout (src  +  1 , dst  +  1 , optsz );
35933601				if  (error ) {
0 commit comments