diff --git a/Pasquale95/README.md b/Pasquale95/README.md new file mode 100644 index 0000000..fab2c02 --- /dev/null +++ b/Pasquale95/README.md @@ -0,0 +1,9 @@ +## General info + +Author: Pasquale Convertini + +See https://github.com/Pasquale95/ for updates and license information. + +## Project list + +- [lsns](https://github.com/Pasquale95/lsns) diff --git a/Pasquale95/lsns.py b/Pasquale95/lsns.py new file mode 100644 index 0000000..2f90e00 --- /dev/null +++ b/Pasquale95/lsns.py @@ -0,0 +1,394 @@ +# Volatility +# Copyright (C) 2007-2013 Volatility Foundation +# +# This file is part of Volatility. +# +# Volatility is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Volatility is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Volatility. If not, see . +# + +""" +@author: Pasquale Convertini +@license: GNU General Public License 2.0 +@contact: pasqualeconvertini95@gmail.com +""" + +import struct + +import volatility.obj as obj +import volatility.utils as utils +import volatility.poolscan as poolscan +import volatility.debug as debug + +import volatility.plugins.linux.common as linux_common +import volatility.plugins.linux.pslist as pslist + + +###################################################### +## UTILITY ## +###################################################### +class nsproxy_struct(object): + ''' Store info contained in each nsproxy + and metadata about the owner process ''' + + def __init__(self, pid, ppid, nmps, command, arguments): + self.pid = pid + self.ppid = ppid + self.uts_ns = nmps[0] + self.ipc_ns = nmps[1] + self.mnt_ns = nmps[2] + self.pid_ns = nmps[3] + self.net_ns = nmps[4] + self.cgroup_ns = nmps[5] + self.user_ns = nmps[6] + self.command = command + self.arguments = arguments + + +###################################################### +## UTILITY ## +###################################################### +class ns_info(object): + ''' Store summary info about a namespace + plus the list of owning processes ''' + + def __init__(self, addr, t, pid, inum=obj.NoneObject()): + self.addr = addr + self.t = t + self.pids = [] + self.pids.append(pid) + self.inum = inum + + def __str__(self): + return "0x{0:x} {1:6s} {2:6s} {3:5s}".format(self.addr, self.t, str(len(self.pids)), str(self.get_ppid())) + + def add_pid(self, pid): + self.pids.append(pid) + + def get_ppid(self): + return sorted(self.pids)[0] + + def get_procs(self): + return sorted(self.pids) + + +###################################################### +## PLUGIN CLASS ## +###################################################### +class lsns(pslist.linux_pslist): + """ Scan memory for Linux namespaces """ + + NUM_NS = 6 #7 namespaces from kernel v4.4 + POINTER_DIM = 8 #bytes + namespaces = {} + ns_structs = {} + + + ################################################ + ## INIT CLASS and CONFIG OPTIONS ## + def __init__(self, config, *args, **kwargs): + linux_common.AbstractLinuxCommand.__init__(self, config, *args, **kwargs) + self._config.add_option('TABLE', short_option = 't', default = None, help = 'print in tabular format', action = 'store_true') + self._config.add_option('INODE', short_option = 'i', default = None, help = 'print inode number instead of offset', action = 'store_true') + self._config.add_option('PID', short_option = 'p', default = None, help = 'Operate on these Process IDs (comma-separated)', action = 'store', type="str") + self._config.add_option('NS', short_option = 'n', default = None, help = 'Operate on these NameSpaces (comma-separated)', action = 'store', type="str") + + + ############################################### + ## STARTING ENGINE OF THE CLASS ## + def calculate(self): + linux_common.set_plugin_members(self) + + #check if architecture is 32: if yes change pointer dim to 4 bytes + if self.addr_space.profile.get_symbol("init_cgroup_ns"): + self.NUM_NS = 7 + + # To enable if you want to give option PID to specify a pid list via cmd look at pslist.py + for task in self.allprocs(): + yield task + + + ################################################ + ## PRINT dim BYTES FROM addr ## + def print_data(self, addr, dim): + data = self.addr_space.read(addr, dim) + for offset, hexchars, chars in utils.Hexdump(data, self.POINTER_DIM): + print "{0:#010x} {1:<48} {2}".format(addr + offset, hexchars, ''.join(chars)) + + + ################################################ + ## RETURN VIRTUAL OR PHYSICAL ADDR ## + def get_address(self, el): + addr = None + if hasattr(self, "wants_physical") and el.obj_vm.base: + nsp = self.addr_space.vtop(el.obj_offset) + if addr == None: + addr = el.obj_offset + return addr + + + ################################################ + ## FILL GLOBAL DICTIONARIES ## + def _get_task_values(self, task): + + if task.parent.is_valid(): + ppid = task.parent.pid + else: + ppid = "-" + + ## CHECK FOR NSPROXY EXISTENCE ## + if task.nsproxy == None: + return False + else: + # GET POINTER TO NSPROXY + nsproxy_obj = obj.Object("nsproxy", vm=self.addr_space, offset=int(task.nsproxy)) + + ## UTS_NS ## + uts_ns = int(nsproxy_obj.uts_ns) + uts_inum = self.get_inode("uts_namespace", uts_ns) + if uts_ns in self.namespaces: + self.namespaces[uts_ns].add_pid(task.pid) + else: + self.namespaces[uts_ns] = ns_info(uts_ns, "uts", task.pid, uts_inum) + + ## IPC_NS ## + ipc_ns = int(nsproxy_obj.ipc_ns) + ipc_inum = self.get_inode("ipc_namespace", ipc_ns) + if ipc_ns in self.namespaces: + self.namespaces[ipc_ns].add_pid(task.pid) + else: + self.namespaces[ipc_ns] = ns_info(ipc_ns, "ipc", task.pid, ipc_inum) + + ## MNT_NS ## + mnt_ns = int(nsproxy_obj.mnt_ns) + mnt_inum = self.get_inode("mnt_namespace", mnt_ns) + if mnt_ns in self.namespaces: + self.namespaces[mnt_ns].add_pid(task.pid) + else: + self.namespaces[mnt_ns] = ns_info(mnt_ns, "mnt", task.pid, mnt_inum) + + ## PID_NS_FOR_CHILDREN ## + pid_ns = int(nsproxy_obj.pid_ns_for_children) + pid_inum = self.get_inode("pid_namespace", pid_ns) + if pid_ns in self.namespaces: + self.namespaces[pid_ns].add_pid(task.pid) + else: + self.namespaces[pid_ns] = ns_info(pid_ns, "pid", task.pid, pid_inum) + + ## NET_NS ## + net_ns = int(nsproxy_obj.net_ns) + net_inum = self.get_inode("net", net_ns) + if net_ns in self.namespaces: + self.namespaces[net_ns].add_pid(task.pid) + else: + self.namespaces[net_ns] = ns_info(net_ns, "net", task.pid, net_inum) + + ## CGROUP_NS -> implemented only from kernel v4.4 ## + if self.NUM_NS == 7: + cgroup_ns = int(nsproxy_obj.cgroup_ns) + cgroup_inum = self.get_inode("cgroup_namespace", cgroup_ns) + if cgroup_ns in self.namespaces: + self.namespaces[cgroup_ns].add_pid(task.pid) + else: + self.namespaces[cgroup_ns] = ns_info(cgroup_ns, "cgroup", task.pid, cgroup_inum) + else: + cgroup_ns = obj.NoneObject() + + ## CHECK FOR CRED STRUCT EXISTENCE ## + if task.cred == None: + user_ns = obj.NoneObject() + else: + # GET POINTER TO CERT + nsproxy_obj = obj.Object("cred", vm=self.addr_space, offset=int(task.cred)) + + ## USER_NS ## + user_ns = int(nsproxy_obj.user_ns) + user_inum = self.get_inode("user_namespace", user_ns) + if user_ns in self.namespaces: + self.namespaces[user_ns].add_pid(task.pid) + else: + self.namespaces[user_ns] = ns_info(user_ns, "user", task.pid, user_inum) + + self.ns_structs[task.pid] = nsproxy_struct(task.pid, ppid, [uts_ns, ipc_ns, mnt_ns, pid_ns, net_ns, cgroup_ns, user_ns], task.comm, task.get_commandline()) + return True + + + ################################################ + ## READ INODE VALUE ## + def get_inode(self, ns_name, offs): + if self.addr_space.profile.has_type(ns_name): + ns_struct = obj.Object(ns_name, vm=self.addr_space, offset=offs) + if hasattr(ns_struct, 'ns'): + ns_n = self.get_address(ns_struct.ns) + ns_obj = obj.Object("ns_common", vm=self.addr_space, offset=ns_n) + return int(ns_obj.inum) + return obj.NoneObject() + + + ################################################ + ## PRINT CHUNK OF DATA ## + def print_data(self, addr, dim): + data = self.addr_space.read(addr, dim) + for offset, hexchars, chars in utils.Hexdump(data, self.POINTER_DIM): + print hexchars + print "" + + + ################################################ + ## READ POINTER VALUE ## + def read_pointer(self, addr, dim): + #print addr + data = self.addr_space.read(addr, dim) + for offset, hexchars, chars in utils.Hexdump(data, dim): + pointer = "0x"+"".join(hexchars.split()[::-1]) + return int(pointer, 16) + + + ################################################ + ## Print for each process all namespaces ## + ## table format ## + def table_format(self, outfd, data): + + if self._config.INODE: + text = "10" + else: + text = "[addrpad]" + + self.table_header(outfd, [("PROCESS", "15"), + ("PID", "5"), + ("uts_ns", text), + ("ipc_ns", text), + ("mnt_ns", text), + ("pid_ns", text), + ("net_ns", text), + ("cgroup_ns", text), + ("user_ns", text)]) + + for task in data: + self._get_task_values(task) + + for key in sorted(self.ns_structs.keys()): + c_p = self.ns_structs[key] + if self._config.INODE: + self.table_row(outfd, c_p.command, c_p.pid, self.namespaces[c_p.uts_ns].inum, self.namespaces[c_p.ipc_ns].inum, self.namespaces[c_p.mnt_ns].inum, self.namespaces[c_p.pid_ns].inum, self.namespaces[c_p.net_ns].inum, self.namespaces[c_p.cgroup_ns].inum, self.namespaces[c_p.user_ns].inum) + else: + self.table_row(outfd, c_p.command, c_p.pid, c_p.uts_ns, c_p.ipc_ns, c_p.mnt_ns, c_p.pid_ns, c_p.net_ns, c_p.cgroup_ns, c_p.user_ns) + + + ################################################ + ## lsns PRINT FORMAT ## + def namespace_format(self, outfd, data): + for task in data: + self._get_task_values(task) + + nslist = self._config.NS + if nslist: + nslist = [int(s, 16) for s in self._config.NS.split(',')] + + ## For each namespace + for ns in nslist: + ## List processes in tree format + if ns in self.namespaces: + outfd.write("\nNAMESPACE: {0:6s} (TYPE: {1})".format(hex(ns), self.namespaces[ns].t)) + if self.namespaces[ns].inum: + outfd.write(" (INODE: {0})".format(int(self.namespaces[ns].inum))) + ## Write header + outfd.write("\n{0:6s} {1:6s} {2:64s}\n".format("PID", "PPID", "COMMAND")) + + procs = [self.ns_structs[a] for a in self.namespaces[ns].get_procs()] + pids = [x.pid for x in procs] + + hierarchy = {} + for proc in sorted(procs, key=lambda x: x.pid): + if proc.ppid not in hierarchy and proc.ppid in pids: + hierarchy[proc.ppid] = [] + elif proc.ppid not in hierarchy and proc.ppid not in pids: + hierarchy[proc.pid] = [] + if proc.ppid in hierarchy: + hierarchy[proc.ppid].append(proc.pid) + already_printed = [] + + for key in sorted(hierarchy.keys()): + if (key not in already_printed): + already_printed = self.printTree(key, hierarchy, already_printed, outfd, ns) + + + ################################################ + ## print like a tree ## + def printTree(self, parent, tree, already_printed, outfd, ns, to_p = '', indent=''): + outfd.write("{0:6s} {1:6s} {2:64s}\n".format(str(parent), str(self.ns_structs[parent].ppid), + to_p+self.ns_structs[parent].arguments)) + if parent not in tree: + already_printed.append(parent) + return already_printed + if tree[parent]: + for child in tree[parent][:-1]: + aa = indent + u'\u251C' + u'\u2500 '#|- + already_printed = self.printTree(child, tree, already_printed, outfd, ns, aa, indent + u'\u2502 ') + child = tree[parent][-1] + aa = indent + u'\u2514' + u'\u2500 '#`- + self.printTree(child, tree, already_printed, outfd, ns, aa, indent + ' '), + already_printed.append(parent) + return already_printed + + + ################################################ + ## lsns print for each PID FORMAT ## + def pid_format(self, outfd, data): + for task in data: + self._get_task_values(task) + + pidlist = self._config.PID + if pidlist: + pidlist = [a for a in self.ns_structs.keys() for p in self._config.PID.split(',') if int(p) == a] + + for pid in pidlist: + if pid in self.ns_structs.keys(): + outfd.write("\nPID: {0:6s}\n".format(str(pid))) + #Print header + self.table_header(outfd, [("NS_offset", "[addrpad]"), ("NS", "10"),("TYPE", "6"), ("NSPROC", "6"), ("PID", "5"), ("COMMAND", "100")]) + + #Print rows + curr_pid = self.ns_structs[pid] + ns = [curr_pid.uts_ns, curr_pid.ipc_ns, curr_pid.mnt_ns, curr_pid.pid_ns, curr_pid.net_ns, curr_pid.cgroup_ns, curr_pid.user_ns] + for i_n in ns: + if i_n in self.namespaces: + n = self.namespaces[i_n] + self.table_row(outfd, n.addr, n.inum, n.t, str(len(n.get_procs())), str(n.get_ppid()), self.ns_structs[n.get_ppid()].arguments) + + + ################################################ + ## CLASSIC lsns PRINT FORMAT ## + def classic_format(self, outfd, data): + for task in data: + self._get_task_values(task) + self.table_header(outfd, [("NSPACE_Offset", "[addrpad]"), ("NS", "10"), ("TYPE", "6"), ("NSPROC", "6"), ("PID", "5"), ("COMMAND", "15"), ("ARGUMENTS", "100")]) + + for key in sorted(self.namespaces.keys(), reverse=True): + curr_ns = self.namespaces[key] + self.table_row(outfd, key, curr_ns.inum, curr_ns.t, len(curr_ns.get_procs()), curr_ns.get_ppid(), self.ns_structs[curr_ns.get_ppid()].command, self.ns_structs[curr_ns.get_ppid()].arguments) + + + ###################################################### + ## OUTPUT ## + ###################################################### + def render_text(self, outfd, data): + if(self._config.TABLE): + self.table_format(outfd, data) + elif(self._config.NS): + self.namespace_format(outfd, data) + elif(self._config.PID): + self.pid_format(outfd, data) + else: + self.classic_format(outfd, data) + diff --git a/Pasquale95/module.c b/Pasquale95/module.c new file mode 100644 index 0000000..c2c43d0 --- /dev/null +++ b/Pasquale95/module.c @@ -0,0 +1,714 @@ +/* + This module does absolutely nothings at all. We just build it with debugging +symbols and then read the DWARF symbols from it. +*/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) +#include +struct ipc_namespace ipc_namespace; + +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,20,0) +struct xa_node xa; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) +#include +struct lockref lockref; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else +#include +#endif + +#include +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) +#include +struct pid_namespace pid_namespace; +#endif + + +#ifdef CONFIG_NETFILTER +#include + +struct nf_hook_ops nf_hook_ops; +struct nf_sockopt_ops nf_sockopt_ops; + +#ifdef CONFIG_NETFILTER_XTABLES +#include +struct xt_table xt_table; +#endif + +#endif + +#include +#include +#include + +#include +#include + +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) +struct atomic_notifier_head atomic_notifier_head; +#endif + +#include +struct tty_driver tty_driver; + +#include +struct tty_struct tty_struct; + +struct udp_seq_afinfo udp_seq_afinfo; +struct tcp_seq_afinfo tcp_seq_afinfo; + +struct files_struct files_struct; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) +struct uts_namespace uts_namespace; +#endif + +struct sock sock; +struct inet_sock inet_sock; +struct vfsmount vfsmount; +struct in_device in_device; +struct fib_table fib_table; +struct unix_sock unix_sock; +struct pid pid; +struct radix_tree_root radix_tree_root; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) +#ifdef CONFIG_NET_SCHED +#include +struct Qdisc qdisc; +#endif +#endif + +struct inet_protosw inet_protosw; + +/******************************************************************** +The following structs are not defined in headers, so we cant import +them. Hopefully they dont change too much. +*********************************************************************/ + +struct kthread_create_info +{ + /* Information passed to kthread() from kthreadd. */ + int (*threadfn)(void *data); + void *data; + int node; + + /* Result passed back to kthread_create() from kthreadd. */ + struct task_struct *result; + struct completion done; + + struct list_head list; +}; + +struct kthread_create_info kthread_create_info; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#include +#endif + +#include +#include +#include +#include + +#define EMBEDDED_HASH_SIZE (L1_CACHE_BYTES / sizeof(struct hlist_head)) + +#define __rcu + +struct fn_zone { + struct fn_zone *fz_next; /* Next not empty zone */ + struct hlist_head *fz_hash; /* Hash table pointer */ + seqlock_t fz_lock; + u32 fz_hashmask; /* (fz_divisor - 1) */ + u8 fz_order; /* Zone order (0..32) */ + u8 fz_revorder; /* 32 - fz_order */ + __be32 fz_mask; /* inet_make_mask(order) */ + + struct hlist_head fz_embedded_hash[EMBEDDED_HASH_SIZE]; + + int fz_nent; /* Number of entries */ + int fz_divisor; /* Hash size (mask+1) */ +} fn_zone; + +struct fn_hash { + struct fn_zone *fn_zones[33]; + struct fn_zone *fn_zone_list; +} fn_hash; + +struct fib_alias +{ + struct list_head fa_list; + struct fib_info *fa_info; + u8 fa_tos; + u8 fa_type; + u8 fa_scope; + u8 fa_state; +#ifdef CONFIG_IP_FIB_TRIE + struct rcu_head rcu; +#endif +}; + +struct fib_node +{ + struct hlist_node fn_hash; + struct list_head fn_alias; + __be32 fn_key; + struct fib_alias fn_embedded_alias; +}; + + +struct fib_node fib_node; +struct fib_alias fib_alias; + +struct rt_hash_bucket { + struct rtable __rcu *chain; +} rt_hash_bucket; + +#ifndef RADIX_TREE_MAP_SHIFT + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +#define RADIX_TREE_MAP_SHIFT 6 +#else +#define RADIX_TREE_MAP_SHIFT (CONFIG_BASE_SMALL ? 4 : 6) +#endif +#define RADIX_TREE_MAP_SIZE (1UL << RADIX_TREE_MAP_SHIFT) +#define RADIX_TREE_MAP_MASK (RADIX_TREE_MAP_SIZE-1) +#define RADIX_TREE_TAG_LONGS ((RADIX_TREE_MAP_SIZE + BITS_PER_LONG - 1) / BITS_PER_LONG) +#define RADIX_TREE_MAX_TAGS 2 + +struct radix_tree_node { + unsigned int height; /* Height from the bottom */ + unsigned int count; + struct rcu_head rcu_head; + void *slots[RADIX_TREE_MAP_SIZE]; + unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS]; +}; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) +#define OUR_OWN_MOD_STRUCTS +#endif + +#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18) +#define OUR_OWN_MOD_STRUCTS +#endif + +#ifdef OUR_OWN_MOD_STRUCTS +struct module_sect_attr +{ + struct module_attribute mattr; + char *name; + unsigned long address; +}; + +struct module_sect_attrs +{ + struct attribute_group grp; + unsigned int nsections; + struct module_sect_attr attrs[0]; +}; + +struct module_sect_attrs module_sect_attrs; + +#else + +struct module_sections module_sect_attrs; + +#endif + +struct module_kobject module_kobject; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0) +// we can't get the defintion of mod_tree_root directly +// because it is declared in module.c as a static struct +// the latch_tree_root struct has the variables we want +// immediately after it though + +#include + +struct latch_tree_root ltr; + +#endif + +#ifdef CONFIG_SLAB + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) +/* + * struct kmem_cache + * + * manages a cache. + */ + +struct kmem_cache { +/* 1) per-cpu data, touched during every alloc/free */ + struct array_cache *array[NR_CPUS]; +/* 2) Cache tunables. Protected by cache_chain_mutex */ + unsigned int batchcount; + unsigned int limit; + unsigned int shared; + + unsigned int buffer_size; + u32 reciprocal_buffer_size; +/* 3) touched by every alloc & free from the backend */ + + unsigned int flags; /* constant flags */ + unsigned int num; /* # of objs per slab */ + +/* 4) cache_grow/shrink */ + /* order of pgs per slab (2^n) */ + unsigned int gfporder; + + /* force GFP flags, e.g. GFP_DMA */ + gfp_t gfpflags; + + size_t colour; /* cache colouring range */ + unsigned int colour_off; /* colour offset */ + struct kmem_cache *slabp_cache; + unsigned int slab_size; + unsigned int dflags; /* dynamic flags */ + + /* constructor func */ + void (*ctor)(void *obj); + +/* 5) cache creation/removal */ + const char *name; + struct list_head next; + +/* 6) statistics */ +#if STATS + unsigned long num_active; + unsigned long num_allocations; + unsigned long high_mark; + unsigned long grown; + unsigned long reaped; + unsigned long errors; + unsigned long max_freeable; + unsigned long node_allocs; + unsigned long node_frees; + unsigned long node_overflow; + atomic_t allochit; + atomic_t allocmiss; + atomic_t freehit; + atomic_t freemiss; +#endif +#if DEBUG + /* + * If debugging is enabled, then the allocator can add additional + * fields and/or padding to every object. buffer_size contains the total + * object size including these internal fields, the following two + * variables contain the offset to the user object and its size. + */ + int obj_offset; + int obj_size; +#endif + /* + * We put nodelists[] at the end of kmem_cache, because we want to size + * this array to nr_node_ids slots instead of MAX_NUMNODES + * (see kmem_cache_init()) + * We still use [MAX_NUMNODES] and not [1] or [0] because cache_cache + * is statically defined, so we reserve the max number of nodes. + */ + struct kmem_list3 *nodelists[MAX_NUMNODES]; + /* + * Do not add fields after nodelists[] + */ +}; +#else + +struct kmem_cache { +/* 1) per-cpu data, touched during every alloc/free */ + struct array_cache *array[NR_CPUS]; +/* 2) Cache tunables. Protected by cache_chain_mutex */ + unsigned int batchcount; + unsigned int limit; + unsigned int shared; + + unsigned int buffer_size; +/* 3) touched by every alloc & free from the backend */ + struct kmem_list3 *nodelists[MAX_NUMNODES]; + + unsigned int flags; /* constant flags */ + unsigned int num; /* # of objs per slab */ + +/* 4) cache_grow/shrink */ + /* order of pgs per slab (2^n) */ + unsigned int gfporder; + + /* force GFP flags, e.g. GFP_DMA */ + gfp_t gfpflags; + + size_t colour; /* cache colouring range */ + unsigned int colour_off; /* colour offset */ + struct kmem_cache *slabp_cache; + unsigned int slab_size; + unsigned int dflags; /* dynamic flags */ + + /* constructor func */ + void (*ctor) (void *, struct kmem_cache *, unsigned long); + + /* de-constructor func */ + void (*dtor) (void *, struct kmem_cache *, unsigned long); + +/* 5) cache creation/removal */ + const char *name; + struct list_head next; + +/* 6) statistics */ +#if STATS + unsigned long num_active; + unsigned long num_allocations; + unsigned long high_mark; + unsigned long grown; + unsigned long reaped; + unsigned long errors; + unsigned long max_freeable; + unsigned long node_allocs; + unsigned long node_frees; + unsigned long node_overflow; + atomic_t allochit; + atomic_t allocmiss; + atomic_t freehit; + atomic_t freemiss; +#endif +#if DEBUG + /* + * If debugging is enabled, then the allocator can add additional + * fields and/or padding to every object. buffer_size contains the total + * object size including these internal fields, the following two + * variables contain the offset to the user object and its size. + */ + int obj_offset; + int obj_size; +#endif +}; + +#endif /*kmem_cache decl*/ + +struct kmem_cache kmem_cache; +#endif + +struct kmem_list3 { + struct list_head slabs_partial; /* partial list first, better asm code */ + struct list_head slabs_full; + struct list_head slabs_free; + unsigned long free_objects; + unsigned int free_limit; + unsigned int colour_next; /* Per-node cache coloring */ + spinlock_t list_lock; + struct array_cache *shared; /* shared per node */ + struct array_cache **alien; /* on other nodes */ + unsigned long next_reap; /* updated without locking */ + int free_touched; /* updated without locking */ +}; + +struct kmem_list3 kmem_list3; + +struct slab { + struct list_head list; + unsigned long colouroff; + void *s_mem; /* including colour offset */ + unsigned int inuse; /* num of objs active in slab */ + unsigned int free; + unsigned short nodeid; + }; + +struct slab slab; +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,31) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) +/* Starting with Linux kernel 3.7 the struct timekeeper is defined in include/linux/timekeeper_internal.h */ +#include +#else +/* Before Linux kernel 3.7 the struct timekeeper has to be taken from kernel/time/timekeeping.c */ + +typedef u64 cycle_t; + +struct timekeeper { + /* Current clocksource used for timekeeping. */ + struct clocksource *clock; + /* NTP adjusted clock multiplier */ + u32 mult; + /* The shift value of the current clocksource. */ + int shift; + + /* Number of clock cycles in one NTP interval. */ + cycle_t cycle_interval; + /* Number of clock shifted nano seconds in one NTP interval. */ + u64 xtime_interval; + /* shifted nano seconds left over when rounding cycle_interval */ + s64 xtime_remainder; + /* Raw nano seconds accumulated per NTP interval. */ + u32 raw_interval; + + /* Clock shifted nano seconds remainder not stored in xtime.tv_nsec. */ + u64 xtime_nsec; + /* Difference between accumulated time and NTP time in ntp + * shifted nano seconds. */ + s64 ntp_error; + /* Shift conversion between clock shifted nano seconds and + * ntp shifted nano seconds. */ + int ntp_error_shift; + + /* The current time */ + struct timespec xtime; + /* + * wall_to_monotonic is what we need to add to xtime (or xtime corrected + * for sub jiffie times) to get to monotonic time. Monotonic is pegged + * at zero at system boot time, so wall_to_monotonic will be negative, + * however, we will ALWAYS keep the tv_nsec part positive so we can use + * the usual normalization. + * + * wall_to_monotonic is moved after resume from suspend for the + * monotonic time not to jump. We need to add total_sleep_time to + * wall_to_monotonic to get the real boot based time offset. + * + * - wall_to_monotonic is no longer the boot time, getboottime must be + * used instead. + */ + struct timespec wall_to_monotonic; + /* time spent in suspend */ + struct timespec total_sleep_time; + /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ + struct timespec raw_time; + + /* Offset clock monotonic -> clock realtime */ + ktime_t offs_real; + + /* Offset clock monotonic -> clock boottime */ + ktime_t offs_boot; + + /* Seqlock for all timekeeper values */ + seqlock_t lock; +}; + +#endif + +struct timekeeper my_timekeeper; + +struct log { + u64 ts_nsec; /* timestamp in nanoseconds */ + u16 len; /* length of entire record */ + u16 text_len; /* length of text buffer */ + u16 dict_len; /* length of dictionary buffer */ + u8 facility; /* syslog facility */ + u8 flags:5; /* internal record flags */ + u8 level:3; /* syslog level */ +}; + +struct log my_log; + +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0) +//deal with the __randomize_layout ? +struct mnt_namespace { + atomic_t count; + struct ns_common ns; + struct mount * root; + struct list_head list; + struct user_namespace *user_ns; + struct ucounts *ucounts; + u64 seq; /* Sequence number to prevent loops */ + wait_queue_head_t poll; + u64 event; + unsigned int mounts; /* # of mounts in the namespace */ + unsigned int pending_mounts; +} __randomize_layout; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0) +struct mnt_namespace { + atomic_t count; + struct ns_common ns; + struct mount * root; + struct list_head list; + struct user_namespace *user_ns; + struct ucounts *ucounts; + u64 seq; /* Sequence number to prevent loops */ + wait_queue_head_t poll; + u64 event; + unsigned int mounts; /* # of mounts in the namespace */ + unsigned int pending_mounts; +}; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) +struct mnt_namespace { + atomic_t count; + struct ns_common ns; + struct mount * root; + struct list_head list; + struct user_namespace *user_ns; + u64 seq; /* Sequence number to prevent loops */ + wait_queue_head_t poll; + u64 event; +}; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,65) +struct mnt_namespace { + atomic_t count; + struct ns_common ns; + struct mount * root; + struct list_head list; + struct user_namespace *user_ns; + u64 seq; /* Sequence number to prevent loops */ + wait_queue_head_t poll; + u64 event; + unsigned int mounts; /* # of mounts in the namespace */ + unsigned int pending_mounts; +}; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) +struct mnt_namespace { + atomic_t count; + struct ns_common ns; + struct mount * root; + struct list_head list; + struct user_namespace *user_ns; + u64 seq; /* Sequence number to prevent loops */ + wait_queue_head_t poll; + u64 event; +}; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) +struct mnt_namespace { + atomic_t count; + unsigned int proc_inum; + struct mount * root; + struct list_head list; + struct user_namespace *user_ns; + u64 seq; /* Sequence number to prevent loops */ + wait_queue_head_t poll; + u64 event; +}; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) +struct mnt_namespace { + atomic_t count; + struct mount * root; + struct list_head list; + wait_queue_head_t poll; + int event; +}; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) +struct mnt_pcp { + int mnt_count; + int mnt_writers; +}; +struct mount { + struct list_head mnt_hash; + struct mount *mnt_parent; + struct dentry *mnt_mountpoint; + struct vfsmount mnt; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) + union { + struct rcu_head mnt_rcu; + struct llist_node mnt_llist; + }; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0) + struct callback_head rcu; +#endif +#ifdef CONFIG_SMP + struct mnt_pcp __percpu *mnt_pcp; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) + atomic_t mnt_longterm; /* how many of the refs are longterm */ +#endif +#else + int mnt_count; + int mnt_writers; +#endif + struct list_head mnt_mounts; /* list of children, anchored here */ + struct list_head mnt_child; /* and going through their mnt_child */ + struct list_head mnt_instance; /* mount instance on sb->s_mounts */ + const char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ + struct list_head mnt_list; + struct list_head mnt_expire; /* link in fs-specific expiry list */ + struct list_head mnt_share; /* circular list of shared mounts */ + struct list_head mnt_slave_list;/* list of slave mounts */ + struct list_head mnt_slave; /* slave list entry */ + struct mount *mnt_master; /* slave is on master->mnt_slave_list */ + struct mnt_namespace *mnt_ns; /* containing namespace */ +#ifdef CONFIG_FSNOTIFY + struct hlist_head mnt_fsnotify_marks; + __u32 mnt_fsnotify_mask; +#endif + int mnt_id; /* mount identifier */ + int mnt_group_id; /* peer group identifier */ + int mnt_expiry_mark; /* true if marked for expiry */ + int mnt_pinned; + int mnt_ghosts; +}; + +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) + struct proc_dir_entry { + unsigned int low_ino; + umode_t mode; + nlink_t nlink; + kuid_t uid; + kgid_t gid; + loff_t size; + const struct inode_operations *proc_iops; + const struct file_operations *proc_fops; + struct proc_dir_entry *next, *parent, *subdir; + void *data; + atomic_t count; /* use count */ + atomic_t in_use; /* number of callers into module in progress; */ + /* negative -> it's going away RSN */ + struct completion *pde_unload_completion; + struct list_head pde_openers; /* who did ->open, but not ->release */ + spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ + u8 namelen; + char name[]; + }; +#else + struct proc_dir_entry { + unsigned int low_ino; + umode_t mode; + nlink_t nlink; + kuid_t uid; + kgid_t gid; + loff_t size; + const struct inode_operations *proc_iops; + const struct file_operations *proc_fops; + struct proc_dir_entry *parent; + struct rb_root subdir; + struct rb_node subdir_node; + void *data; + atomic_t count; /* use count */ + atomic_t in_use; /* number of callers into module in progress; */ + /* negative -> it's going away RSN */ + struct completion *pde_unload_completion; + struct list_head pde_openers; /* who did ->open, but not ->release */ + spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ + u8 namelen; + char name[]; + }; +#endif +#endif + +struct resource resource; +