text processing: security audit and easy porting of patches

Submitted by olecom
on April 16, 2008 - 12:06am

Brad Spengler <spender@grsecurity>:
Due to Linux kernel developers continuing to silently fix exploitable bugs (in particular, trivially exploitable NULL ptr dereference bugs continue to be fixed without any mention of their security implications) we continue to suggest that the 2.6 kernels be avoided if possible.
______
As one of the easy ways of static audit of known misuses of C, known for ages security bugs, kernel (or any other call/return) interfaces to userspace, etc., i am proposing text processing.

Main concept is annotation (much like as sparse annotations for types/memory regions):
* call traces,
* parameters
* and return values useage.

Checking if function/functionality (macro, module, etc.) is uses as annotated, seems like ordinary multiline `grep`, which is `sed`.

Also, annotations can help in porting big patches, gresecurity is. In general, i define annotation as another way of expression of rules, functionality, changes or whatever. While patching with classic `diff`&&`patch` is text based, it has nothing to do with semantic load of that text (what code changes, how it does it, what it adds, what it removes, relations, etc). Another text processing can check semantics:
* variable addition, its usage
* function parameters, its usage
* whole modules with multiple functions and data structures
* addition, usage, etc.

Yea, it's just a handwaving. But to check at least something, i need someone as a partner (i have social problem with very deep longliness). This is why i've started this publication here. Even better thing will be, if this group (if created) will be paid for at least research in/try+implement of this ideas.

There are problems in the Linux as in whole handcrafted programming. But as experimentation with LKML shows, there is a big mismatch of text processing skills (read first post here). Even in sed users list, which i finally have subscribed. Mature member didn't get question/task right. Now he seems to understood that and provided a solution, i've posted already ~5 hour ago (i's yahoo list, whicj is closed to non yahoo users). Thus, maybe no good GSoC mentor can handle proposition and whole that money thing for this research...

cargo cult security: "that vmsplice() fuzz" (thanks to PaX Team)

on
April 16, 2008 - 12:12am
Date: Thu, 13 Mar 2008 22:03:36 +0100
From: "Oleg Verych" 
To: "Jonathan Corbet" 
Subject: that vmsplice() fuzz

> There are a couple of interesting implications from all of this.

Are you serious, Editor?

> One, clearly, is that this exploit is not something which was bashed
> out by a script kiddie somewhere.

You've discovered America! This world called Underground, and small
window to it is [0]. This is "for fun and profit" answer to cargo cult
security (and society[1]).

[0] phrack.org
[1] http://www.planetanalog.com/showArticle.jhtml?articleID=205919937

> It was written by somebody who understands low-level kernel code quite
> well and who is able to use that understanding to escalate an apparent
> information-disclosure vulnerability into a full code execution
> problem. It is, clearly, a mistake to underestimate those who write
> exploits, not all of whom immediately make their works known to the
> development community. One also should not assume that they have not
> already written exploits for other, still unfixed bugs.

Have fun exploring archives of [0].

> Also worth noting is the fact that ordinary buffer overflow protection
> may well have not been effective against this vulnerability. The
> return address on the stack was not overwritten, and no exploit code
> was put in data areas.

Bla, bla, bla. Why don't you consult real security experts[2], before any
claims and statements?

[2] http://www.avertlabs.com/research/blog/index.php/2008/02/13/analyzing-th...

> This episode has caused a renewed interested in technical security
> measures in the kernel. These measures are good, but it would be a
> mistake to think that they will fix the problem. What is really needed
> is stronger review of patches with security in mind; it is not yet
> clear to your editor that this review is happening.

Those measures are just distraction from the cause. Cause is even not
lack of review, but lack of source code audit, automated one.

First incomplete fix of the vmsplice() checking in 2.6.24.1 is cause of
all this fuzz, and even you, dear Editor, didn't get all thing right days
after. A textbook security hole -- not checking user supplied pointer, if
it is a kernel space for operation -- wasn't even expressly mentioned as
stupidly main flaw. And Linus played those taste NULL pointer games in
quite important time[3].

[3] http://article.gmane.org/gmane.linux.kernel/637943

So, what makes an ordinary craft and manu factura an industry? The tools
are main engine of industrial revolutions. Where such tools for source
code audit in leading _open_ source project, Linux kernel is?

I've got no answers on similar trolling, like i do here:

[4] http://article.gmane.org/gmane.linux.kernel/649945
[5] http://article.gmane.org/gmane.linux.kernel/650783

People are tend to do errors, such as not fixing/greping for all known
problems.

Reviewed regular expressions and logic, as in science and ``linux kernel
development'', but not perl or python or any other crap, is IMHO a way
for _open_ source. Because, e.g. *full* version of linux-style function
greping(not small, but still naive [5]) is like below, with many, many
style and whitespace brokenness handling:
(here was the script from kernelnewbiew.org/olecom)
______

leave stupid vmsplice() hole alone finally (GCC 4.3.0 exposes a

on
April 16, 2008 - 12:15am
Date: Mon, 24 Mar 2008 14:09:24 +0100
From: "Oleg Verych" <olecom@>
To: "Linux Weekly News" <lwn@>, "Jonathan Corbet" <corbet@>
Subject: leave stupid vmsplice() hole alone finally (GCC 4.3.0 exposes a kernel bug)

following up http://lwn.net/Articles/272048/

> It is hard to see how that could be turned into a security breach,
> but it would be a mistake to assume that it can't. Other kernel bugs,
> like the one that allowed the recent vmsplice() exploit, have looked
> liked memory corruption, but were found to be more than that.

| After a bit more poking around, we discovered how to alter the page
| mappings so that sections of kernel and I/O memory were directly mapped
| into all user address spaces.[2]

[2] Talk about security holes!
(C) 1992 http://valhenson.org/synthesis/SynthesisOS/ch7.html
http://lwn.net/Articles/270081/

Not checking userspace supplied pointers for being kernel addresses is
most basic security hole in common userspace + kernel address space
memory based systems.
-- 
-o--=O`C
 #oo'L O
<___=E M

more to avertlabs' comments

on
April 19, 2008 - 7:51pm
from
> [2] http://www.avertlabs.com/research/blog/index.php/2008/02/13/analyzing-th...

> To sum up, the exploitation involves:
> 
>  * integer overflow
>  * buffer overflow
>  * mapping the zero address to allow NULL dereference 

So, why they don't tell about two line fix, which shows exactly
why there was a explitable hole and not just steps to walk thru?
Why they don't tell, that 2.6.24.1 had a security fix, which
turned to be incomplete?

I.e. most basic thing: checking address to be not in userspace?

> References
>
> [1] Linux vmsplice Local Root Exploit By qaaz
> [2] Runtime disable of sys_vmsplice
>

And second one is a kernel module. Marvelous!
Userspace sucks, as$ usual!
(Note: Linus uses `make oldconfig` && no modules)

====
From olecom Wed Mar 26 15:03:50 2008
Date: Wed, 26 Mar 2008 15:03:50 +0100
To: klibc list <klibc@>, dash list <dash@>
Subject: nop a syscall (root hole) on 64-bits
Message-ID: <20080326140350.GZ24008@flower.upol.cz>

... or buddy userspace.

patching `sys_vmsplice()' with `ret'.

1)# echo -e '\xc3' | dd of=/dev/kmem bs=1 count=1 seek=$((0x`cat
    /proc/kallsyms|grep sys_vmsplice | awk {'print $1'}`))

2)# echo -e '\xc3' | dd of=/dev/kmem bs=1 count=1 seek=$((0x`awk
    '/sys_vmsplice/ { print $1; }' /proc/kallsyms`))

my try:

#
# printf "\xC3"  |  dd bs=1 count=1 of=/dev/kmem conv=notrunc \
  seek=$((0x`sed -n '/vmsplice$/{s; .*;;p;q}' /boot/S*p-$(uname -r) | tee /dev/stderr`))
ffffffff802cc20f
dd: invalid number `-2144550385'
#
# dash -c 'printf "\xC3"  |  dd bs=1 count=1 of=/dev/kmem conv=notrunc \
  seek=$((0x`sed -n "/vmsplice$/{s; .*;;p;q}" /boot/S*p-$(uname -r) | tee /dev/stderr`))'
ffffffff802cc20f
dd: invalid number `-1'
#
# printf "\xC3"  |  dd bs=1 count=1 of=/dev/kmem conv=notrunc \
  seek=$(printf %u 0x`sed -n '/vmsplice$/{s; .*;;p;q}' /boot/S*p-$(uname -r) | tee /dev/stderr`)
ffffffff802cc20f
dd: `/dev/kmem': cannot seek
0+0 records in
0+0 records out
0 bytes (0 B) copied, 8.1e-05 seconds, 0.0 kB/s
#
# printf "\xC3" | /usr/lib/klibc/bin/dd bs=1 count=1 of=/dev/kmem conv=notrunc \
  seek=$(printf %u 0x`sed -n '/vmsplice$/{s; .*;;p;q}' /boot/S*p-$(uname -r) | tee /dev/stderr`)
ffffffff802cc20f
/usr/lib/klibc/bin/dd: bad operand `seek=18446744071565001231'
#

Nothing. So, i need to reboot or build a kernel module, oh well...
______

My big respect to PaX Team,

on
April 16, 2008 - 10:26am

My big respect to PaX Team, even this is one person, maintaining a dead horse i386 for nearly 8 years... It will be very upsetting, if all wark will be lost in the dust of sky rocketing cracking easy-git-merging-Linux.

Maybe IDL ideas can be aplied here as well: main change log syntax *is* an IDL for automatic text processing, ordinary comments are for humans.

Message-ID: <8499950a0804160557h76975757t64ebead93d376acc@mail.gmail.com>
Date: Wed, 16 Apr 2008 13:57:25 +0100
From: "Oleg Verych" <olecom@>
To: PaX <pageexec@>
Subject: maintaining patches (Re: grsecurity 2.1.11 released for
  Linux 2.4.36.2/2.6.24.4)

Hallo, PaX Team!

>  It is not clear if the PaX Team will be able to continue supporting
>  future versions of the 2.6 kernels, given their rapid rate of release
>  and the incredible amount of work that goes into porting such a
>  low-level enhancement to the kernel (especially now in view of the
>  reworking of the i386/x86-64 trees). It may be necessary that grsecurity
>  instead track the Ubuntu LTS kernel so that users can have a stable
>  kernel with up-to-date security fixes. I will update this page when a
>  final decision has been reached.

Do you have any log about what is going non in PaX patches, test patches?
I'd like to start pure text-based porting of patches, i.e. using
semantic-aware patching, like

* (variable, const, struct) change name, add/del, add initializer, etc (`sed`)
* functions (add, del; add remove parameters, renames) (`sed`)
* function body changes (ordinary `diff` + patch)

This is quite easy (IMHO) to do, but blind batch processing of unknown code
base isn't a good way to go. But with some info from logs, as changed
function foo, renamed task_size to pax_task_size, etc. it will be much easier
and safer (in terms of correct match of automatics).

Even syntax of changelog can be optimized for processing right away, and
only side comments will be as more wide description of action for humans.

So, what do you think?

==
some more handwaving about text processing: http://kerneltrap.org/blog/9104
-- 
sed 'sed && sh + olecom = love' << ''
-o--=O`C
 #oo'L O
<___=E M

Re: maintaining patches (Re: grsecurity 2.1.11 released for Linu

on
April 17, 2008 - 1:55pm
Message-ID: <8499950a0804171050q6c053a60j97dd65da39262512@mail.gmail.com>
Date: Thu, 17 Apr 2008 18:50:39 +0100
From: "Oleg Verych"
To: PaX
Subject: Re: maintaining patches (Re: grsecurity 2.1.11 released for Linux 2.4.36.2/2.6.24.4)

PaX Team @ Thu, Apr 17, 2008 at 2:31 PM:

>  > Even syntax of changelog can be optimized for processing right away, and
>  > only side comments will be as more wide description of action for humans.
>  >
>  > So, what do you think?
>  
>  problem is that what you're trying to do will cover only parts of the
>  changes introduced by PaX and i'm afraid it'll be hard stuff which will
>  fall through the cracks and will still/always require manual porting.

Manual work will be always required in modern handcrafted
programming. I yet to see tools other than 20 years old `diff`+`patch`
(which are part of `git`) and sometimes patch-utils. I try to introduce more
advanced text processing tools. Comprehensive tools are means of industry,
not craft. But as my experience show processing of Linux C codebase is done
purely by code monkey's hands and one-line-match `grep`. They do diff's
rejections resolving manually, and sometimes this leads to mismerges
(broken actual C code of an author). git helps to distribute this dump job,
Linus and Alan were doing for a decade.

>  two examples:
>  
>  - for years now i've been reverting the per-CPU GDT changes in 2.6. this
>   affects several files and results in removing/adding entire code blocks
>   that you won't be easily able to capture with text matching. just look
>   at for example how the per-CPU GDT is initialized vs. how PaX does it.

text matching of whole codeblocks as long as functions and datastructures
in main tree don't change names is easy. I.e. i can remove or move to
#ifdef/#endif any complete code block (function, datastructure) in any
given file/set of files. Tool is `sed`, which is for me is powerful,
more easy to do huge work and more readable, than `perl` (or any other
scripting language).

Tracking of changes in main tree of those files WRT given set of names --
is kind of infrastructure i need, to make manual search/change more easy.

Changes inside functions are relatively hard, because it is classical
diff+patch with all that reject/mismerge stuff.

Automation is for easier work, not complete substitution (checking always
must be done my knowledgeable humans)

>  - early PAE boot. before 2.6.25 linux would use two different kinds of
>   page table setups when using a PAE kernel. the early boot tables would
>   be only 2 levels, later the kernel would switch to the 3-level PAE ones.
>   i modified this to always use one kind and threw out/simplified a lot
>   of code on the way. first, i don't see how your tracking would cope with
>   this when such early boot code changes, second, how would it detect that
>   vanilla linux *itself* changed and made my changes obsolete (or not, i
>   haven't checked that they did everything PaX does).

diff+patch as above, if modification is done inside functions. But to make
it easier, i propose, to have whole patch to be split in parts and sometimes
sent to LKML for review, so same monkeys will say if something was changed
really hard.

>  > Do you have any log about what is going non in PaX patches, test patches?
>  
>  no, i don't keep a changelog for 2.6, but i have a full archive of all
>  -testXX patches if that's of any help.

Yes it will help to reconstruct changes step by step. But it will be really helpful,
if new changes will be logged. Thus i can see modification patterns more easily,
for example.

It will be really too wasteful, if no changelogs and no info about PaX
codebase is available, and suddenly everything will stop (ubuntu kernel,
any other cause).

This is why even without that whole text processing magic, PaX needs to
be published in LKML, for review (which is kind of ghost there), for
attraction and collaboration.

What i can do now is pure C semantic/plain text automation of patching and
describing of (some) changes, i am new to whole underground security stuff...

-- 
sed 'sed && sh + olecom = love' << ''
-o--=O`C
 #oo'L O
<___=E M

review 40% from bottom of pax-linux-2.6.24.4-test42.patch

on
April 19, 2008 - 8:40pm
From olecom Fri Apr 18 07:52:29 2008
Date: Fri, 18 Apr 2008 07:52:29 +0200
To: PaX
Subject: review 40% from bottom of pax-linux-2.6.24.4-test42.patch
Message-ID: <20080418055229.GK24008@flower.upol.cz>

Hallo. Just started to look and see :)

Some easy-to-do things i'll do soon, so code itself will the
main target.


== repeated patterns are for `sed` ==
-	struct nfs4_exception exception = { };
+	struct nfs4_exception exception = {0, 0};
 	int err;
 	do {
 		err = nfs4_handle_exception(server,
@@ -2345,7 +2345,7 @@ static int _nfs4_do_fsinfo(struct nfs_se
 
 static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
 {
-	struct nfs4_exception exception = { };
+	struct nfs4_exception exception = {0, 0};
 	int err;
 
 	do {
@@ -2388,7 +2388,7 @@ static int _nfs4_proc_pathconf(struct nf
 static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
 		struct nfs_pathconf *pathconf)
 {
-	struct nfs4_exception exception = { };
+	struct nfs4_exception exception = {0, 0};


== $ARCH code copies ==
--- linux-2.6.24.4/include/asm-*/pgtable.h	2008-01-24 23:58:37.000000000 +0100
+++ linux-2.6.24.4-pax/include/asm-*/pgtable.h	2008-02-29 18:07:50.000000000 +0100

huge chunks of same asm-$ARCH/* can be copied by `sed`

and thing like this:
-D(14)	KM_TYPE_NR
+D(14)	KM_CLEARPAGE,
+D(15)	KM_TYPE_NR

is very easy job for `sed` also

== typo? ==
-	sprintf(path, "/sys/block/%s/dev", name);
-	fd = sys_open(path, 0, 0);
+	if (sizeof path <= snprintf(path, sizeof path, "/sys/block/%s/dev", name))
                  ^^^^^^

typo or OK?

== loads of annotations/phony do {} while  ==
+	fd = sys_open((char __user *)path, 0, 0);
 	if (fd < 0)
 		goto fail;
-	len = sys_read(fd, buf, 32);
+	len = sys_read(fd, (char __user *)buf, 32);

i can give it for free with `sed`, as well as

-#define SCTP_DEBUG_PRINTK(whatever...)
-#define SCTP_DEBUG_PRINTK_IPADDR(whatever...)
+#define SCTP_DEBUG_PRINTK(whatever...) do {} while (0)
+#define SCTP_DEBUG_PRINTK_IPADDR(whatever...) do {} while (0)

OK, this is the most easy part, so script will be in today or quite soon

==
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (write_access || !pax_find_mirror_vma(vma))
+#endif
+
 	unlock_page(page);

if it's OK, maybe a macro will be better?

== no indent ==

+#ifdef CONFIG_PAX_SEGMEXEC
+	if (mm->pax_flags & MF_PAX_SEGMEXEC) {
+		if (end > SEGMEXEC_TASK_SIZE)
+			return -EINVAL;
+	} else
+#endif
+
+	if (end > TASK_SIZE)
+		return -EINVAL;

no indent is OK?


== macro? ==
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if ((vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) && vma->vm_start == SEGMEXEC_TASK_SIZE)
+		return 0;
+#endif
+
 	if (is_mergeable_vma(vma, file, vm_flags) &&
 	    is_mergeable_anon_vma(anon_vma, vma->anon_vma)) {
 		if (vma->vm_pgoff == vm_pgoff)
@@ -695,6 +724,12 @@ static int
 can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags,
 	struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff)
 {
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if ((vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) && vma->vm_end == SEGMEXEC_TASK_SIZE)
+		return 0;
+#endif
+

macro?

== whilespace ==

-		     	struct anon_vma *anon_vma, struct file *file,
+			struct anon_vma *anon_vma, struct file *file,

sometimes it seems, like somebody does whitespace cleanup, but it's not
fully automated or done by emacs...

====

 void vm_stat_account(struct mm_struct *mm, unsigned long flags,
 						struct file *file, long pages)
 {
-	const unsigned long stack_flags
-		= VM_STACK_FLAGS & (VM_GROWSUP|VM_GROWSDOWN);
-
 	if (file) {
 		mm->shared_vm += pages;
 		if ((flags & (VM_EXEC|VM_WRITE)) == VM_EXEC)
 			mm->exec_vm += pages;
-	} else if (flags & stack_flags)
+	} else if (flags & (VM_GROWSUP|VM_GROWSDOWN))
 		mm->stack_vm += pages;

real crap or just optimization?

-	error = arch_mmap_check(addr, len, flags);
-	if (error)
-		return error;
-
 	/* Careful about overflows.. */
 	len = PAGE_ALIGN(len);
 	if (!len || len > TASK_SIZE)
 		return -ENOMEM;
 
+	error = arch_mmap_check(addr, len, flags);
+	if (error)
+		return error;
+

4mainline fix, or whatever?


-	unsigned int vm_flags = vma->vm_flags;
+	unsigned long vm_flags = vma->vm_flags;

i always wonder about all those int/longs dance in 32/64 bits.
What is that this time? Maybe this is pure 4mainline stuff?

 	/* If it was private or non-writable, the write bit is already clear */
-	if ((vm_flags & (VM_WRITE|VM_SHARED)) != ((VM_WRITE|VM_SHARED)))
+	if ((vm_flags & (VM_WRITE|VM_SHARED)) != (VM_WRITE|VM_SHARED))

too LISPy ?-)

==
+#ifdef CONFIG_PAX_RANDMMAP
+	if (!(mm->pax_flags & MF_PAX_RANDMMAP))
+#endif
+
 	/* requesting a specific address */
 	if (addr) {
 		addr = PAGE_ALIGN(addr);

is this a way of patching with small impact or error?

==
+	charged = len >> PAGE_SHIFT;
[...]
seems like good performance and size optimization


==
+		error = __do_munmap(mm, start_m, end_m - start_m);
+		if (error)
+			return -ENOMEM;

here is just a return, but

+	}
+#endif
+
 	/*
 	 * If we make a private mapping writable we increase our commit;
 	 * but (without finer accounting) cannot reduce our commit if we
@@ -186,6 +264,25 @@ mprotect_fixup(struct vm_area_struct *vm
 			goto fail;
 	}
 
+#ifdef CONFIG_PAX_SEGMEXEC
+	if ((mm->pax_flags & MF_PAX_SEGMEXEC) && !(oldflags & VM_EXEC) && (newflags & VM_EXEC)) {
+		struct mempolicy *pol;
+
+		vma_m = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
+		if (!vma_m) {
+			error = -ENOMEM;
+			goto fail;

here is goto...

==

+static inline void pax_handle_maywrite(struct vm_area_struct *vma, unsigned long start)
+{
+	struct elfhdr elf_h;
+	struct elf_phdr elf_p;
+	elf_addr_t dyn_offset = 0UL;
+	elf_dyn dyn;
+	unsigned long i, j = 65536UL / sizeof(struct elf_phdr);

i wonder why there's 0UL (zero UL), 65536 instead of (1UL << 16)


+#ifndef CONFIG_PAX_NOELFRELOCS
+	if ((vma->vm_start != start) ||
+	    !vma->vm_file ||
+	    !(vma->vm_flags & VM_MAYEXEC) ||
+	    (vma->vm_flags & VM_MAYNOTWRITE))
+#endif
+
+		return;

this return seem out of #ifndef block

+
+	if (sizeof(elf_h) != kernel_read(vma->vm_file, 0UL, (char *)&elf_h, sizeof(elf_h)) ||
+	    memcmp(elf_h.e_ident, ELFMAG, SELFMAG) ||
+
+#ifdef CONFIG_PAX_ETEXECRELOCS
+	    (elf_h.e_type != ET_DYN && elf_h.e_type != ET_EXEC) ||
+#else
+	    elf_h.e_type != ET_DYN ||
+#endif
+
+	    !elf_check_arch(&elf_h) ||
+	    elf_h.e_phentsize != sizeof(struct elf_phdr) ||
+	    elf_h.e_phnum > j)
+		return;

so ugly; maybe to set up some #defines for this?

+	for (i = 0UL; i < elf_h.e_phnum; i++) {
+		if (sizeof(elf_p) != kernel_read(vma->vm_file, elf_h.e_phoff + i*sizeof(elf_p), (char *)&elf_p, sizeof(elf_p)))
+			return;

coding style thing (screen width)

+		if (elf_p.p_type == PT_DYNAMIC) {
+			dyn_offset = elf_p.p_offset;
+			j = i;
+		}
+	}
+	if (elf_h.e_phnum <= j)
+		return;
+
+	i = 0UL;
+	do {
+		if (sizeof(dyn) != kernel_read(vma->vm_file, dyn_offset + i*sizeof(dyn), (char *)&dyn, sizeof(dyn)))
+			return;

this kernel_read() and above can be a macro for sure, or whole if() even

+		if (dyn.d_tag == DT_TEXTREL || (dyn.d_tag == DT_FLAGS && (dyn.d_un.d_val & DF_TEXTREL))) {
+			vma->vm_flags |= VM_MAYWRITE | VM_MAYNOTWRITE;
+			return;
+		}
+		i++;
+	} while (dyn.d_tag != DT_NULL);
+	return;
+}
______

more text-related propositions

on
April 19, 2008 - 8:44pm
From olecom Fri Apr 18 11:25:00 2008
Date: Fri, 18 Apr 2008 11:25:00 +0200
To: PaX
Subject: more text-related propositions (Re: review 40% from bottom of pax-linux-2.6.24.4-test42.patch)

My view of another #ifdef'ery. main goals:

+ readability of main C code
+ finding semantic units
+ code (this units) reuse
- syntax of meta-code is kind of unusual for most programmers

input:

+unsigned long
+arch_get_unmapped_area(struct file *filp, unsigned long addr,
+               unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+       struct mm_struct *mm = current->mm;
+       struct vm_area_struct *vma;
+       unsigned long start_addr, pax_task_size = TASK_SIZE;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+       if (mm->pax_flags & MF_PAX_SEGMEXEC)
+               pax_task_size = SEGMEXEC_TASK_SIZE;
+#endif
+
+       if (len > pax_task_size)
+               return -ENOMEM;
+
+       if (flags & MAP_FIXED)
+               return addr;
+
+#ifdef CONFIG_PAX_RANDMMAP
+       if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
+#endif
+
+       if (addr) {
+               addr = PAGE_ALIGN(addr);
+               vma = find_vma(mm, addr);
+               if (pax_task_size - len >= addr &&
+                   (!vma || addr + len <= vma->vm_start))
+                       return addr;
+       }

output:
+
unsigned long
arch_get_unmapped_area(struct file *filp, unsigned long addr,
               unsigned long len, unsigned long pgoff, unsigned long flags)
{
       struct mm_struct *mm = current->mm;
       struct vm_area_struct *vma;

       unsigned long start_addr, pax_task_size;

       if (flags & MAP_FIXED)
               return addr;

       set_pax_task_size();

       if (len > pax_task_size)
               return -ENOMEM;

       if (CHECK_PAX_RANDMMAP && addr) {
               addr = PAGE_ALIGN(addr);
               vma = find_vma(mm, addr);
               if (pax_task_size - len >= addr &&
                   (!vma || addr + len <= vma->vm_start))
                       return addr;
       }
+

where below are meta constructs in shell, ugly? non maintainable?
(even this can be generated, but i'm not sure about more
readable syntax)

set_pax_task_size(){
       local out='
       pax_task_size = TASK_SIZE;
'
       [ "$PAX_SEGMEXEC" ] && out='
       if (mm->pax_flags & MF_PAX_SEGMEXEC)
               pax_task_size = SEGMEXEC_TASK_SIZE;
       else
'$out
       echo "$out"
}

CHECK_PAX_RANDMMAP(){
       local out=1
       
       [ "PAX_RANDMMAP" ] && out='
       (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)'

       echo "$out"
}

non diff-like example: subsitute copy_* macro

on
April 19, 2008 - 8:53pm
From olecom Fri Apr 18 13:06:40 2008
Date: Fri, 18 Apr 2008 13:06:40 +0200
To: PaX
Subject: non diff-like example: subsitute copy_* macro (Re: more text-related propositions...)

#!/bin/sh

WRAP_ASM='
/^[[:blank:]]*__asm__/{
:_asm
n
s " \\" g
s ^.*$ "&\\\\n"\\ ;
/^"\/\* asm end \*\//!b_asm
d
}
'
pax_copy_to_user(){
sed '$!s $ \\ ;'"$WRAP_ASM" << '# pax_copy_end'
static unsigned long
__generic_copy_to_user(void __user *to, const void *from, unsigned long size)
{
	int __d0, __d1, __d2;

	__asm__ __volatile__(
	movw %w8,%%es
	cmp  $7,%0
	jbe  1f
	movl %1,%0
	negl %0
	andl $7,%0
	subl %0,%3
4:	rep; movsb
	movl %3,%0
	shrl $2,%0
	andl $3,%3
	.align 2,0x90
0:	rep; movsl
	movl %3,%0
1:	rep; movsb
2:
	pushl %%ss
	popl %%es
.section .fixup,"ax"
5:	addl %3,%0
	jmp 2b
3:	lea 0(%3,%0,4),%0
	jmp 2b
.previous
.section __ex_table,"a"
	.align 4
	.long 4b,5b
	.long 0b,3b
	.long 1b,2b
.previous
/* asm end */
	: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2)
	: "3"(size), "0"(size), "1"(to), "2"(from), "r"(__USER_DS)
	: "memory");

	return size;
}

static unsigned long
__generic_copy_from_user(void *to, const void __user *from, unsigned long size)
{
	int __d0, __d1, __d2;

	__asm__ __volatile__(
	movw %w8,%%ds
	cmp  $7,%0
	jbe  1f
	movl %1,%0
	negl %0
	andl $7,%0
	subl %0,%3
4:	rep; movsb
	movl %3,%0
	shrl $2,%0
	andl $3,%3
	.align 2,0x90
0:	rep; movsl
	movl %3,%0
1:	rep; movsb
2:
	pushl %%ss
	popl %%ds
.section .fixup,"ax"
5:	addl %3,%0
	jmp 2b
3:	lea 0(%3,%0,4),%0
	jmp 2b
.previous
.section __ex_table,"a"
	.align 4
	.long 4b,5b
	.long 0b,3b
	.long 1b,2b
.previous
/* asm end */
	: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2)
	: "3"(size), "0"(size), "1"(to), "2"(from), "r"(__USER_DS)
	: "memory");

	return size;
}

static unsigned long
__copy_user_zeroing(void *to, const void __user *from, unsigned long size)
{
	int __d0, __d1, __d2;

	__asm__ __volatile__(
	movw %w8,%%ds
	cmp  $7,%0
	jbe  1f
	movl %1,%0
	negl %0
	andl $7,%0
	subl %0,%3
4:	rep; movsb
	movl %3,%0
	shrl $2,%0
	andl $3,%3
	.align 2,0x90
0:	rep; movsl
	movl %3,%0
1:	rep; movsb
2:
	pushl %%ss
	popl %%ds
.section .fixup,"ax"
5:	addl %3,%0
	jmp 6f
3:	lea 0(%3,%0,4),%0
6:	pushl %0
	pushl %%eax
	xorl %%eax,%%eax
	rep; stosb
	popl %%eax
	popl %0
	jmp 2b
.previous
.section __ex_table,"a"
	.align 4
	.long 4b,5b
	.long 0b,3b
	.long 1b,6b
.previous
/* asm end */
	: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2)
	: "3"(size), "0"(size), "1"(to), "2"(from), "r"(__USER_DS)
	: "memory");

	return size;
}
/* voila */
# pax_copy_end
}

RM_C_MACRO=':_line;n;/\\$/b_line;'

sed -n '
/^#define __copy_user(to,from,size)/{'"$RM_C_MACRO"'d;}
/^#define __copy_user_zeroing(to,from,size)/{'"$RM_C_MACRO"'n;c \
'"`pax_copy_to_user`"'
;
}
p
' << "EOF"
/* test: original code start */
#endif /* CONFIG_X86_INTEL_USERCOPY */

/* Generic arbitrary sized copy.  */
#define __copy_user(to,from,size)					\
do {									\
	int __d0, __d1, __d2;						\
	__asm__ __volatile__(						\
		"	cmp  $7,%0\n"					\
		"	jbe  1f\n"					\
		"	movl %1,%0\n"					\
		"	negl %0\n"					\
		"	andl $7,%0\n"					\
		"	subl %0,%3\n"					\
		"4:	rep; movsb\n"					\
		"	movl %3,%0\n"					\
		"	shrl $2,%0\n"					\
		"	andl $3,%3\n"					\
		"	.align 2,0x90\n"				\
		"0:	rep; movsl\n"					\
		"	movl %3,%0\n"					\
		"1:	rep; movsb\n"					\
		"2:\n"							\
		".section .fixup,\"ax\"\n"				\
		"5:	addl %3,%0\n"					\
		"	jmp 2b\n"					\
		"3:	lea 0(%3,%0,4),%0\n"				\
		"	jmp 2b\n"					\
		".previous\n"						\
		".section __ex_table,\"a\"\n"				\
		"	.align 4\n"					\
		"	.long 4b,5b\n"					\
		"	.long 0b,3b\n"					\
		"	.long 1b,2b\n"					\
		".previous"						\
		: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2)	\
		: "3"(size), "0"(size), "1"(to), "2"(from)		\
		: "memory");						\
} while (0)

#define __copy_user_zeroing(to,from,size)				\
do {									\
	int __d0, __d1, __d2;						\
	__asm__ __volatile__(						\
		"	cmp  $7,%0\n"					\
		"	jbe  1f\n"					\
		"	movl %1,%0\n"					\
		"	negl %0\n"					\
		"	andl $7,%0\n"					\
		"	subl %0,%3\n"					\
		"4:	rep; movsb\n"					\
		"	movl %3,%0\n"					\
		"	shrl $2,%0\n"					\
		"	andl $3,%3\n"					\
		"	.align 2,0x90\n"				\
		"0:	rep; movsl\n"					\
		"	movl %3,%0\n"					\
		"1:	rep; movsb\n"					\
		"2:\n"							\
		".section .fixup,\"ax\"\n"				\
		"5:	addl %3,%0\n"					\
		"	jmp 6f\n"					\
		"3:	lea 0(%3,%0,4),%0\n"				\
		"6:	pushl %0\n"					\
		"	pushl %%eax\n"					\
		"	xorl %%eax,%%eax\n"				\
		"	rep; stosb\n"					\
		"	popl %%eax\n"					\
		"	popl %0\n"					\
		"	jmp 2b\n"					\
		".previous\n"						\
		".section __ex_table,\"a\"\n"				\
		"	.align 4\n"					\
		"	.long 4b,5b\n"					\
		"	.long 0b,3b\n"					\
		"	.long 1b,6b\n"					\
		".previous"						\
		: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2)	\
		: "3"(size), "0"(size), "1"(to), "2"(from)		\
		: "memory");						\
} while (0)

/* original code end */
EOF

batch conversion: phony macro && asm !volatile

on
April 19, 2008 - 8:56pm
From olecom Fri Apr 18 23:24:11 2008
Date: Fri, 18 Apr 2008 23:24:11 +0200
To: PaX
Subject: batch conversion: phony macro && asm !volatile

#!/bin/sh

# space and tab, it's short [[:blank:]]
S=`printf '[ \t]'`
sed "
# phony macro -> do {} while (0)
/^#$S*define$S*[^ (]*([^)]*)$S*\(\/\*.*\*\/$S*\)*$/{
s-)$S*\(/[*].*[*]/\)*.*-)\tdo {} while (0)-
}
# asm -> asm volatile
/$S*_*asm_*$S*(/{
s-\(asm\(_*\)\)$S*-\1 \2volatile\2 -
}
" << '___test'

#define LIST_POISON1  ((void *) 0xFF1001FFFF1001FFULL)
#define LIST_POISON2  ((void *) 0xFF2002FFFF2002FFULL)
#define MF_PAX_PAGEEXEC                0x01000000      /* Paging based non-executable pages */
#define MF_PAX_EMUTRAMP                0x02000000      /* Emulate trampolines */

#define jbd_debug(f, a...)     /**/
#define snd_BUG()                      /* nothing */

#define snd_pcm_oss_proc_init(pcm)
#define snd_pcm_oss_proc_done(pcm)

#define snd_use_lock_init(lockp) /**/
#define snd_use_lock_use(lockp) /**/
#define snd_use_lock_free(lockp) /**/
#define snd_use_lock_sync(lockp) /**/

               asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
               asm("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx));
               asm("cpuid"

   __asm__ __volatile (
   __asm__ (

___test

just a bright day

on
April 19, 2008 - 9:39pm
All other days, i just sit in depression and wait for
something...

This blog doesn't change anything WRT finding colleagues,
as it seems.

I was even silently banned from my native country's
bone-headed forum.linux.by .

Silently, like last dictator in Europe -- by.president
kills and punishes by.citizens. Like that police
gorillaz, silently hammering students and alike on
peaceful protests, right after the Sun comes down.

Oh, crap.
--
sed 'sed && sh + olecom = love' << ''
-o--=O`C
 #oo'L O
<___=E M

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.