@@ -5998,18 +5998,9 @@ EXPORT_SYMBOL_GPL(perf_event_period);
59985998
59995999static const struct file_operations perf_fops ;
60006000
6001- static inline int perf_fget_light ( int fd , struct fd * p )
6001+ static inline bool is_perf_file ( struct fd f )
60026002{
6003- struct fd f = fdget (fd );
6004- if (!fd_file (f ))
6005- return - EBADF ;
6006-
6007- if (fd_file (f )-> f_op != & perf_fops ) {
6008- fdput (f );
6009- return - EBADF ;
6010- }
6011- * p = f ;
6012- return 0 ;
6003+ return !fd_empty (f ) && fd_file (f )-> f_op == & perf_fops ;
60136004}
60146005
60156006static int perf_event_set_output (struct perf_event * event ,
@@ -6057,20 +6048,14 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
60576048
60586049 case PERF_EVENT_IOC_SET_OUTPUT :
60596050 {
6060- int ret ;
6051+ CLASS (fd , output )(arg ); // arg == -1 => empty
6052+ struct perf_event * output_event = NULL ;
60616053 if (arg != -1 ) {
6062- struct perf_event * output_event ;
6063- struct fd output ;
6064- ret = perf_fget_light (arg , & output );
6065- if (ret )
6066- return ret ;
6054+ if (!is_perf_file (output ))
6055+ return - EBADF ;
60676056 output_event = fd_file (output )-> private_data ;
6068- ret = perf_event_set_output (event , output_event );
6069- fdput (output );
6070- } else {
6071- ret = perf_event_set_output (event , NULL );
60726057 }
6073- return ret ;
6058+ return perf_event_set_output ( event , output_event ) ;
60746059 }
60756060
60766061 case PERF_EVENT_IOC_SET_FILTER :
@@ -12664,7 +12649,6 @@ SYSCALL_DEFINE5(perf_event_open,
1266412649 struct perf_event_attr attr ;
1266512650 struct perf_event_context * ctx ;
1266612651 struct file * event_file = NULL ;
12667- struct fd group = EMPTY_FD ;
1266812652 struct task_struct * task = NULL ;
1266912653 struct pmu * pmu ;
1267012654 int event_fd ;
@@ -12735,10 +12719,12 @@ SYSCALL_DEFINE5(perf_event_open,
1273512719 if (event_fd < 0 )
1273612720 return event_fd ;
1273712721
12722+ CLASS (fd , group )(group_fd ); // group_fd == -1 => empty
1273812723 if (group_fd != -1 ) {
12739- err = perf_fget_light ( group_fd , & group );
12740- if ( err )
12724+ if (! is_perf_file ( group )) {
12725+ err = - EBADF ;
1274112726 goto err_fd ;
12727+ }
1274212728 group_leader = fd_file (group )-> private_data ;
1274312729 if (flags & PERF_FLAG_FD_OUTPUT )
1274412730 output_event = group_leader ;
@@ -12750,7 +12736,7 @@ SYSCALL_DEFINE5(perf_event_open,
1275012736 task = find_lively_task_by_vpid (pid );
1275112737 if (IS_ERR (task )) {
1275212738 err = PTR_ERR (task );
12753- goto err_group_fd ;
12739+ goto err_fd ;
1275412740 }
1275512741 }
1275612742
@@ -13017,12 +13003,11 @@ SYSCALL_DEFINE5(perf_event_open,
1301713003 mutex_unlock (& current -> perf_event_mutex );
1301813004
1301913005 /*
13020- * Drop the reference on the group_event after placing the
13021- * new event on the sibling_list. This ensures destruction
13022- * of the group leader will find the pointer to itself in
13023- * perf_group_detach().
13006+ * File reference in group guarantees that group_leader has been
13007+ * kept alive until we place the new event on the sibling_list.
13008+ * This ensures destruction of the group leader will find
13009+ * the pointer to itself in perf_group_detach().
1302413010 */
13025- fdput (group );
1302613011 fd_install (event_fd , event_file );
1302713012 return event_fd ;
1302813013
@@ -13041,8 +13026,6 @@ SYSCALL_DEFINE5(perf_event_open,
1304113026err_task :
1304213027 if (task )
1304313028 put_task_struct (task );
13044- err_group_fd :
13045- fdput (group );
1304613029err_fd :
1304713030 put_unused_fd (event_fd );
1304813031 return err ;
0 commit comments