@@ -277,78 +277,86 @@ void put_cmsg_scm_timestamping(struct msghdr *msg, struct scm_timestamping_inter
277277}
278278EXPORT_SYMBOL (put_cmsg_scm_timestamping );
279279
280+ static int __scm_install_fd (struct file * file , int __user * ufd , int o_flags )
281+ {
282+ struct socket * sock ;
283+ int new_fd ;
284+ int error ;
285+
286+ error = security_file_receive (file );
287+ if (error )
288+ return error ;
289+
290+ new_fd = get_unused_fd_flags (o_flags );
291+ if (new_fd < 0 )
292+ return new_fd ;
293+
294+ error = put_user (new_fd , ufd );
295+ if (error ) {
296+ put_unused_fd (new_fd );
297+ return error ;
298+ }
299+
300+ /* Bump the usage count and install the file. */
301+ sock = sock_from_file (file , & error );
302+ if (sock ) {
303+ sock_update_netprioidx (& sock -> sk -> sk_cgrp_data );
304+ sock_update_classid (& sock -> sk -> sk_cgrp_data );
305+ }
306+ fd_install (new_fd , get_file (file ));
307+ return error ;
308+ }
309+
310+ static int scm_max_fds (struct msghdr * msg )
311+ {
312+ if (msg -> msg_controllen <= sizeof (struct cmsghdr ))
313+ return 0 ;
314+ return (msg -> msg_controllen - sizeof (struct cmsghdr )) / sizeof (int );
315+ }
316+
280317void scm_detach_fds (struct msghdr * msg , struct scm_cookie * scm )
281318{
282319 struct cmsghdr __user * cm
283320 = (__force struct cmsghdr __user * )msg -> msg_control ;
284-
285- int fdmax = 0 ;
286- int fdnum = scm -> fp -> count ;
287- struct file * * fp = scm -> fp -> fp ;
288- int __user * cmfptr ;
321+ int o_flags = (msg -> msg_flags & MSG_CMSG_CLOEXEC ) ? O_CLOEXEC : 0 ;
322+ int fdmax = min_t (int , scm_max_fds (msg ), scm -> fp -> count );
323+ int __user * cmsg_data = CMSG_USER_DATA (cm );
289324 int err = 0 , i ;
290325
291- if (MSG_CMSG_COMPAT & msg -> msg_flags ) {
326+ if (msg -> msg_flags & MSG_CMSG_COMPAT ) {
292327 scm_detach_fds_compat (msg , scm );
293328 return ;
294329 }
295330
296- if (msg -> msg_controllen > sizeof (struct cmsghdr ))
297- fdmax = ((msg -> msg_controllen - sizeof (struct cmsghdr ))
298- / sizeof (int ));
299-
300- if (fdnum < fdmax )
301- fdmax = fdnum ;
302-
303- for (i = 0 , cmfptr = (int __user * )CMSG_USER_DATA (cm ); i < fdmax ;
304- i ++ , cmfptr ++ )
305- {
306- struct socket * sock ;
307- int new_fd ;
308- err = security_file_receive (fp [i ]);
331+ for (i = 0 ; i < fdmax ; i ++ ) {
332+ err = __scm_install_fd (scm -> fp -> fp [i ], cmsg_data + i , o_flags );
309333 if (err )
310334 break ;
311- err = get_unused_fd_flags (MSG_CMSG_CLOEXEC & msg -> msg_flags
312- ? O_CLOEXEC : 0 );
313- if (err < 0 )
314- break ;
315- new_fd = err ;
316- err = put_user (new_fd , cmfptr );
317- if (err ) {
318- put_unused_fd (new_fd );
319- break ;
320- }
321- /* Bump the usage count and install the file. */
322- sock = sock_from_file (fp [i ], & err );
323- if (sock ) {
324- sock_update_netprioidx (& sock -> sk -> sk_cgrp_data );
325- sock_update_classid (& sock -> sk -> sk_cgrp_data );
326- }
327- fd_install (new_fd , get_file (fp [i ]));
328335 }
329336
330- if (i > 0 )
331- {
332- int cmlen = CMSG_LEN ( i * sizeof ( int ));
337+ if (i > 0 ) {
338+ int cmlen = CMSG_LEN ( i * sizeof ( int ));
339+
333340 err = put_user (SOL_SOCKET , & cm -> cmsg_level );
334341 if (!err )
335342 err = put_user (SCM_RIGHTS , & cm -> cmsg_type );
336343 if (!err )
337344 err = put_user (cmlen , & cm -> cmsg_len );
338345 if (!err ) {
339- cmlen = CMSG_SPACE (i * sizeof (int ));
346+ cmlen = CMSG_SPACE (i * sizeof (int ));
340347 if (msg -> msg_controllen < cmlen )
341348 cmlen = msg -> msg_controllen ;
342349 msg -> msg_control += cmlen ;
343350 msg -> msg_controllen -= cmlen ;
344351 }
345352 }
346- if (i < fdnum || (fdnum && fdmax <= 0 ))
353+
354+ if (i < scm -> fp -> count || (scm -> fp -> count && fdmax <= 0 ))
347355 msg -> msg_flags |= MSG_CTRUNC ;
348356
349357 /*
350- * All of the files that fit in the message have had their
351- * usage counts incremented, so we just free the list.
358+ * All of the files that fit in the message have had their usage counts
359+ * incremented, so we just free the list.
352360 */
353361 __scm_destroy (scm );
354362}
0 commit comments