@@ -5998,18 +5998,9 @@ EXPORT_SYMBOL_GPL(perf_event_period);
5998
5998
5999
5999
static const struct file_operations perf_fops ;
6000
6000
6001
- static inline int perf_fget_light ( int fd , struct fd * p )
6001
+ static inline bool is_perf_file ( struct fd f )
6002
6002
{
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 ;
6013
6004
}
6014
6005
6015
6006
static 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
6057
6048
6058
6049
case PERF_EVENT_IOC_SET_OUTPUT :
6059
6050
{
6060
- int ret ;
6051
+ CLASS (fd , output )(arg ); // arg == -1 => empty
6052
+ struct perf_event * output_event = NULL ;
6061
6053
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 ;
6067
6056
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 );
6072
6057
}
6073
- return ret ;
6058
+ return perf_event_set_output ( event , output_event ) ;
6074
6059
}
6075
6060
6076
6061
case PERF_EVENT_IOC_SET_FILTER :
@@ -12664,7 +12649,6 @@ SYSCALL_DEFINE5(perf_event_open,
12664
12649
struct perf_event_attr attr ;
12665
12650
struct perf_event_context * ctx ;
12666
12651
struct file * event_file = NULL ;
12667
- struct fd group = EMPTY_FD ;
12668
12652
struct task_struct * task = NULL ;
12669
12653
struct pmu * pmu ;
12670
12654
int event_fd ;
@@ -12735,10 +12719,12 @@ SYSCALL_DEFINE5(perf_event_open,
12735
12719
if (event_fd < 0 )
12736
12720
return event_fd ;
12737
12721
12722
+ CLASS (fd , group )(group_fd ); // group_fd == -1 => empty
12738
12723
if (group_fd != -1 ) {
12739
- err = perf_fget_light ( group_fd , & group );
12740
- if ( err )
12724
+ if (! is_perf_file ( group )) {
12725
+ err = - EBADF ;
12741
12726
goto err_fd ;
12727
+ }
12742
12728
group_leader = fd_file (group )-> private_data ;
12743
12729
if (flags & PERF_FLAG_FD_OUTPUT )
12744
12730
output_event = group_leader ;
@@ -12750,7 +12736,7 @@ SYSCALL_DEFINE5(perf_event_open,
12750
12736
task = find_lively_task_by_vpid (pid );
12751
12737
if (IS_ERR (task )) {
12752
12738
err = PTR_ERR (task );
12753
- goto err_group_fd ;
12739
+ goto err_fd ;
12754
12740
}
12755
12741
}
12756
12742
@@ -13017,12 +13003,11 @@ SYSCALL_DEFINE5(perf_event_open,
13017
13003
mutex_unlock (& current -> perf_event_mutex );
13018
13004
13019
13005
/*
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().
13024
13010
*/
13025
- fdput (group );
13026
13011
fd_install (event_fd , event_file );
13027
13012
return event_fd ;
13028
13013
@@ -13041,8 +13026,6 @@ SYSCALL_DEFINE5(perf_event_open,
13041
13026
err_task :
13042
13027
if (task )
13043
13028
put_task_struct (task );
13044
- err_group_fd :
13045
- fdput (group );
13046
13029
err_fd :
13047
13030
put_unused_fd (event_fd );
13048
13031
return err ;
0 commit comments