From: Thomas Lamprecht Date: Tue, 18 Jul 2017 12:53:59 +0000 (+0200) Subject: add CVE fixes X-Git-Url: https://git.proxmox.com/?p=pve-kernel.git;a=commitdiff_plain;h=4c390211d88a2e586f9ea5946c66237284db698b add CVE fixes CVE-2017-1000364 (rather bugfix for the original CVE fix): * mm/mmap.c: expand_downwards: don't require the gap if !vm_prev * mm/mmap.c: do not blow on PROT_NONE MAP_FIXED holes in the stack CVE-2017-1000365: fs/exec.c: account for argv/envp pointers CVE-2017-10810: drm/virtio: don't leak bo on drm_gem_object_init failure CVE-2017-7482: rxrpc: Fix several cases where a padded len isn't checked in ticket decode Signed-off-by: Thomas Lamprecht --- diff --git a/CVE-2017-1000364-mm-mmap.c-do-not-blow-on-PROT_NONE-MAP_FIXED-holes-i.patch b/CVE-2017-1000364-mm-mmap.c-do-not-blow-on-PROT_NONE-MAP_FIXED-holes-i.patch new file mode 100644 index 0000000..75b4522 --- /dev/null +++ b/CVE-2017-1000364-mm-mmap.c-do-not-blow-on-PROT_NONE-MAP_FIXED-holes-i.patch @@ -0,0 +1,72 @@ +From 3e4f09eef73ad12d4876e24daf52a0dc0891d7da Mon Sep 17 00:00:00 2001 +From: Michal Hocko +Date: Mon, 17 Jul 2017 14:53:28 +0200 +Subject: [PATCH 1/2] mm/mmap.c: do not blow on PROT_NONE MAP_FIXED holes in + the stack + +Commit 1be7107fbe18 ("mm: larger stack guard gap, between vmas") has +introduced a regression in some rust and Java environments which are +trying to implement their own stack guard page. They are punching a new +MAP_FIXED mapping inside the existing stack Vma. + +This will confuse expand_{downwards,upwards} into thinking that the +stack expansion would in fact get us too close to an existing non-stack +vma which is a correct behavior wrt safety. It is a real regression on +the other hand. + +Let's work around the problem by considering PROT_NONE mapping as a part +of the stack. This is a gros hack but overflowing to such a mapping +would trap anyway an we only can hope that usespace knows what it is +doing and handle it propely. + +Fixes: 1be7107fbe18 ("mm: larger stack guard gap, between vmas") +Link: http://lkml.kernel.org/r/20170705182849.GA18027@dhcp22.suse.cz +Signed-off-by: Michal Hocko +Debugged-by: Vlastimil Babka +Cc: Ben Hutchings +Cc: Willy Tarreau +Cc: Oleg Nesterov +Cc: Rik van Riel +Cc: Hugh Dickins +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds + +CVE-2017-1000364 + +(cherry picked from commit 561b5e0709e4a248c67d024d4d94b6e31e3edf2f) +Signed-off-by: Stefan Bader +Acked-by: Kleber Sacilotto de Souza +Acked-by: Kamal Mostafa +Signed-off-by: Kleber Sacilotto de Souza +Signed-off-by: Thomas Lamprecht +--- + mm/mmap.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/mm/mmap.c b/mm/mmap.c +index ef78a5ca5599..9fabd8c82f38 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -2240,7 +2240,8 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address) + gap_addr = TASK_SIZE; + + next = vma->vm_next; +- if (next && next->vm_start < gap_addr) { ++ if (next && next->vm_start < gap_addr && ++ (next->vm_flags & (VM_WRITE|VM_READ|VM_EXEC))) { + if (!(next->vm_flags & VM_GROWSUP)) + return -ENOMEM; + /* Check that both stack segments have the same anon_vma? */ +@@ -2324,7 +2325,8 @@ int expand_downwards(struct vm_area_struct *vma, + if (gap_addr > address) + return -ENOMEM; + prev = vma->vm_prev; +- if (prev && prev->vm_end > gap_addr) { ++ if (prev && prev->vm_end > gap_addr && ++ (prev->vm_flags & (VM_WRITE|VM_READ|VM_EXEC))) { + if (!(prev->vm_flags & VM_GROWSDOWN)) + return -ENOMEM; + /* Check that both stack segments have the same anon_vma? */ +-- +2.11.0 + diff --git a/CVE-2017-1000364-mm-mmap.c-expand_downwards-don-t-require-the-gap-if-.patch b/CVE-2017-1000364-mm-mmap.c-expand_downwards-don-t-require-the-gap-if-.patch new file mode 100644 index 0000000..6fa4bfb --- /dev/null +++ b/CVE-2017-1000364-mm-mmap.c-expand_downwards-don-t-require-the-gap-if-.patch @@ -0,0 +1,71 @@ +From aea792ba99ba73a6b0c4e5aea3b4b6b3f9d821f6 Mon Sep 17 00:00:00 2001 +From: Oleg Nesterov +Date: Mon, 17 Jul 2017 14:53:29 +0200 +Subject: [PATCH 2/2] mm/mmap.c: expand_downwards: don't require the gap if + !vm_prev + +expand_stack(vma) fails if address < stack_guard_gap even if there is no +vma->vm_prev. I don't think this makes sense, and we didn't do this +before the recent commit 1be7107fbe18 ("mm: larger stack guard gap, +between vmas"). + +We do not need a gap in this case, any address is fine as long as +security_mmap_addr() doesn't object. + +This also simplifies the code, we know that address >= prev->vm_end and +thus underflow is not possible. + +Link: http://lkml.kernel.org/r/20170628175258.GA24881@redhat.com +Signed-off-by: Oleg Nesterov +Acked-by: Michal Hocko +Cc: Hugh Dickins +Cc: Larry Woodman +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds + +CVE-2017-1000364 + +(cherry picked from commit 32e4e6d5cbb0c0e427391635991fe65e17797af8) +Signed-off-by: Stefan Bader +Acked-by: Kleber Sacilotto de Souza +Acked-by: Kamal Mostafa +Signed-off-by: Kleber Sacilotto de Souza +Signed-off-by: Thomas Lamprecht +--- + mm/mmap.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/mm/mmap.c b/mm/mmap.c +index 9fabd8c82f38..09c728a1eeee 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -2312,7 +2312,6 @@ int expand_downwards(struct vm_area_struct *vma, + { + struct mm_struct *mm = vma->vm_mm; + struct vm_area_struct *prev; +- unsigned long gap_addr; + int error; + + address &= PAGE_MASK; +@@ -2321,15 +2320,12 @@ int expand_downwards(struct vm_area_struct *vma, + return error; + + /* Enforce stack_guard_gap */ +- gap_addr = address - stack_guard_gap; +- if (gap_addr > address) +- return -ENOMEM; + prev = vma->vm_prev; +- if (prev && prev->vm_end > gap_addr && ++ /* Check that both stack segments have the same anon_vma? */ ++ if (prev && !(prev->vm_flags & VM_GROWSDOWN) && + (prev->vm_flags & (VM_WRITE|VM_READ|VM_EXEC))) { +- if (!(prev->vm_flags & VM_GROWSDOWN)) ++ if (address - prev->vm_end < stack_guard_gap) + return -ENOMEM; +- /* Check that both stack segments have the same anon_vma? */ + } + + /* We must make sure the anon_vma is allocated. */ +-- +2.11.0 + diff --git a/CVE-2017-1000365-fs-exec.c-account-for-argv-envp-pointers.patch b/CVE-2017-1000365-fs-exec.c-account-for-argv-envp-pointers.patch new file mode 100644 index 0000000..e85ea99 --- /dev/null +++ b/CVE-2017-1000365-fs-exec.c-account-for-argv-envp-pointers.patch @@ -0,0 +1,99 @@ +From 6b44f156198491839655077fc7f3a469c67e1f8d Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 12 Jul 2017 15:30:39 +0200 +Subject: [PATCH 2/3] fs/exec.c: account for argv/envp pointers + +When limiting the argv/envp strings during exec to 1/4 of the stack limit, +the storage of the pointers to the strings was not included. This means +that an exec with huge numbers of tiny strings could eat 1/4 of the stack +limit in strings and then additional space would be later used by the +pointers to the strings. + +For example, on 32-bit with a 8MB stack rlimit, an exec with 1677721 +single-byte strings would consume less than 2MB of stack, the max (8MB / +4) amount allowed, but the pointers to the strings would consume the +remaining additional stack space (1677721 * 4 == 6710884). + +The result (1677721 + 6710884 == 8388605) would exhaust stack space +entirely. Controlling this stack exhaustion could result in +pathological behavior in setuid binaries (CVE-2017-1000365). + +[akpm@linux-foundation.org: additional commenting from Kees] +Fixes: b6a2fea39318 ("mm: variable length argument support") +Link: http://lkml.kernel.org/r/20170622001720.GA32173@beast +Signed-off-by: Kees Cook +Acked-by: Rik van Riel +Acked-by: Michal Hocko +Cc: Alexander Viro +Cc: Qualys Security Advisory +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds + +CVE-2017-1000365 + +(cherry-picked from commit 98da7d08850fb8bdeb395d6368ed15753304aa0c) +Signed-off-by: Stefan Bader +Acked-by: Thadeu Lima de Souza Cascardo +Acked-by: Seth Forshee +Signed-off-by: Thadeu Lima de Souza Cascardo + +Signed-off-by: Thomas Lamprecht +--- + fs/exec.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/fs/exec.c b/fs/exec.c +index 9fb90c37c37f..8cf76e2a0b83 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -225,8 +225,26 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, + + if (write) { + unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; ++ unsigned long ptr_size; + struct rlimit *rlim; + ++ /* ++ * Since the stack will hold pointers to the strings, we ++ * must account for them as well. ++ * ++ * The size calculation is the entire vma while each arg page is ++ * built, so each time we get here it's calculating how far it ++ * is currently (rather than each call being just the newly ++ * added size from the arg page). As a result, we need to ++ * always add the entire size of the pointers, so that on the ++ * last call to get_arg_page() we'll actually have the entire ++ * correct size. ++ */ ++ ptr_size = (bprm->argc + bprm->envc) * sizeof(void *); ++ if (ptr_size > ULONG_MAX - size) ++ goto fail; ++ size += ptr_size; ++ + acct_arg_size(bprm, size / PAGE_SIZE); + + /* +@@ -244,13 +262,15 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, + * to work from. + */ + rlim = current->signal->rlim; +- if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) { +- put_page(page); +- return NULL; +- } ++ if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) ++ goto fail; + } + + return page; ++ ++fail: ++ put_page(page); ++ return NULL; + } + + static void put_arg_page(struct page *page) +-- +2.11.0 + diff --git a/CVE-2017-10810-drm-virtio-don-t-leak-bo-on-drm_gem_object_init-fail.patch b/CVE-2017-10810-drm-virtio-don-t-leak-bo-on-drm_gem_object_init-fail.patch new file mode 100644 index 0000000..8065b6e --- /dev/null +++ b/CVE-2017-10810-drm-virtio-don-t-leak-bo-on-drm_gem_object_init-fail.patch @@ -0,0 +1,43 @@ +From de1c3d4474562e9d9dc9952f9283f07d8d58ef98 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 12 Jul 2017 12:35:52 +0200 +Subject: [PATCH 1/3] drm/virtio: don't leak bo on drm_gem_object_init failure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reported-by: 李强 +Signed-off-by: Gerd Hoffmann +Link: http://patchwork.freedesktop.org/patch/msgid/20170406155941.458-1-kraxel@redhat.com + +CVE-2017-10810 + +(cherry picked from commit 385aee965b4e4c36551c362a334378d2985b722a) +Signed-off-by: Stefan Bader +Acked-by: Seth Forshee +Acked-by: Kleber Sacilotto de Souza +Signed-off-by: Thadeu Lima de Souza Cascardo +Signed-off-by: Thomas Lamprecht +--- + drivers/gpu/drm/virtio/virtgpu_object.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c +index 1483daebe057..6f66b7347cd0 100644 +--- a/drivers/gpu/drm/virtio/virtgpu_object.c ++++ b/drivers/gpu/drm/virtio/virtgpu_object.c +@@ -81,8 +81,10 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, + return -ENOMEM; + size = roundup(size, PAGE_SIZE); + ret = drm_gem_object_init(vgdev->ddev, &bo->gem_base, size); +- if (ret != 0) ++ if (ret != 0) { ++ kfree(bo); + return ret; ++ } + bo->dumb = false; + virtio_gpu_init_ttm_placement(bo, pinned); + +-- +2.11.0 + diff --git a/CVE-2017-7482-rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch b/CVE-2017-7482-rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch new file mode 100644 index 0000000..937d6a6 --- /dev/null +++ b/CVE-2017-7482-rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch @@ -0,0 +1,215 @@ +From 453b5039843f7dac534ee23af6b34c2d0a116416 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 12 Jul 2017 16:30:25 +0200 +Subject: [PATCH 3/3] rxrpc: Fix several cases where a padded len isn't checked + in ticket decode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This fixes CVE-2017-7482. + +When a kerberos 5 ticket is being decoded so that it can be loaded into an +rxrpc-type key, there are several places in which the length of a +variable-length field is checked to make sure that it's not going to +overrun the available data - but the data is padded to the nearest +four-byte boundary and the code doesn't check for this extra. This could +lead to the size-remaining variable wrapping and the data pointer going +over the end of the buffer. + +Fix this by making the various variable-length data checks use the padded +length. + +Reported-by: 石磊 +Signed-off-by: David Howells +Reviewed-by: Marc Dionne +Reviewed-by: Dan Carpenter +Signed-off-by: David S. Miller + +CVE-2017-7482 + +(cherry-picked from commit 5f2f97656ada8d811d3c1bef503ced266fcd53a0) +Signed-off-by: Stefan Bader +Acked-by: Seth Forshee +Acked-by: Kleber Sacilotto de Souza +Signed-off-by: Thadeu Lima de Souza Cascardo + +Signed-off-by: Thomas Lamprecht +--- + net/rxrpc/key.c | 64 ++++++++++++++++++++++++++++++--------------------------- + 1 file changed, 34 insertions(+), 30 deletions(-) + +diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c +index 18c737a61d80..7fc340726d03 100644 +--- a/net/rxrpc/key.c ++++ b/net/rxrpc/key.c +@@ -217,7 +217,7 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, + unsigned int *_toklen) + { + const __be32 *xdr = *_xdr; +- unsigned int toklen = *_toklen, n_parts, loop, tmp; ++ unsigned int toklen = *_toklen, n_parts, loop, tmp, paddedlen; + + /* there must be at least one name, and at least #names+1 length + * words */ +@@ -247,16 +247,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, + toklen -= 4; + if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX) + return -EINVAL; +- if (tmp > toklen) ++ paddedlen = (tmp + 3) & ~3; ++ if (paddedlen > toklen) + return -EINVAL; + princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL); + if (!princ->name_parts[loop]) + return -ENOMEM; + memcpy(princ->name_parts[loop], xdr, tmp); + princ->name_parts[loop][tmp] = 0; +- tmp = (tmp + 3) & ~3; +- toklen -= tmp; +- xdr += tmp >> 2; ++ toklen -= paddedlen; ++ xdr += paddedlen >> 2; + } + + if (toklen < 4) +@@ -265,16 +265,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, + toklen -= 4; + if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX) + return -EINVAL; +- if (tmp > toklen) ++ paddedlen = (tmp + 3) & ~3; ++ if (paddedlen > toklen) + return -EINVAL; + princ->realm = kmalloc(tmp + 1, GFP_KERNEL); + if (!princ->realm) + return -ENOMEM; + memcpy(princ->realm, xdr, tmp); + princ->realm[tmp] = 0; +- tmp = (tmp + 3) & ~3; +- toklen -= tmp; +- xdr += tmp >> 2; ++ toklen -= paddedlen; ++ xdr += paddedlen >> 2; + + _debug("%s/...@%s", princ->name_parts[0], princ->realm); + +@@ -293,7 +293,7 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td, + unsigned int *_toklen) + { + const __be32 *xdr = *_xdr; +- unsigned int toklen = *_toklen, len; ++ unsigned int toklen = *_toklen, len, paddedlen; + + /* there must be at least one tag and one length word */ + if (toklen <= 8) +@@ -307,15 +307,17 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td, + toklen -= 8; + if (len > max_data_size) + return -EINVAL; ++ paddedlen = (len + 3) & ~3; ++ if (paddedlen > toklen) ++ return -EINVAL; + td->data_len = len; + + if (len > 0) { + td->data = kmemdup(xdr, len, GFP_KERNEL); + if (!td->data) + return -ENOMEM; +- len = (len + 3) & ~3; +- toklen -= len; +- xdr += len >> 2; ++ toklen -= paddedlen; ++ xdr += paddedlen >> 2; + } + + _debug("tag %x len %x", td->tag, td->data_len); +@@ -387,7 +389,7 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, + const __be32 **_xdr, unsigned int *_toklen) + { + const __be32 *xdr = *_xdr; +- unsigned int toklen = *_toklen, len; ++ unsigned int toklen = *_toklen, len, paddedlen; + + /* there must be at least one length word */ + if (toklen <= 4) +@@ -399,6 +401,9 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, + toklen -= 4; + if (len > AFSTOKEN_K5_TIX_MAX) + return -EINVAL; ++ paddedlen = (len + 3) & ~3; ++ if (paddedlen > toklen) ++ return -EINVAL; + *_tktlen = len; + + _debug("ticket len %u", len); +@@ -407,9 +412,8 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, + *_ticket = kmemdup(xdr, len, GFP_KERNEL); + if (!*_ticket) + return -ENOMEM; +- len = (len + 3) & ~3; +- toklen -= len; +- xdr += len >> 2; ++ toklen -= paddedlen; ++ xdr += paddedlen >> 2; + } + + *_xdr = xdr; +@@ -552,7 +556,7 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) + { + const __be32 *xdr = prep->data, *token; + const char *cp; +- unsigned int len, tmp, loop, ntoken, toklen, sec_ix; ++ unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix; + size_t datalen = prep->datalen; + int ret; + +@@ -578,22 +582,21 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) + if (len < 1 || len > AFSTOKEN_CELL_MAX) + goto not_xdr; + datalen -= 4; +- tmp = (len + 3) & ~3; +- if (tmp > datalen) ++ paddedlen = (len + 3) & ~3; ++ if (paddedlen > datalen) + goto not_xdr; + + cp = (const char *) xdr; + for (loop = 0; loop < len; loop++) + if (!isprint(cp[loop])) + goto not_xdr; +- if (len < tmp) +- for (; loop < tmp; loop++) +- if (cp[loop]) +- goto not_xdr; ++ for (; loop < paddedlen; loop++) ++ if (cp[loop]) ++ goto not_xdr; + _debug("cellname: [%u/%u] '%*.*s'", +- len, tmp, len, len, (const char *) xdr); +- datalen -= tmp; +- xdr += tmp >> 2; ++ len, paddedlen, len, len, (const char *) xdr); ++ datalen -= paddedlen; ++ xdr += paddedlen >> 2; + + /* get the token count */ + if (datalen < 12) +@@ -614,10 +617,11 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) + sec_ix = ntohl(*xdr); + datalen -= 4; + _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix); +- if (toklen < 20 || toklen > datalen) ++ paddedlen = (toklen + 3) & ~3; ++ if (toklen < 20 || toklen > datalen || paddedlen > datalen) + goto not_xdr; +- datalen -= (toklen + 3) & ~3; +- xdr += (toklen + 3) >> 2; ++ datalen -= paddedlen; ++ xdr += paddedlen >> 2; + + } while (--loop > 0); + +-- +2.11.0 + diff --git a/Makefile b/Makefile index 85dc178..c961e42 100644 --- a/Makefile +++ b/Makefile @@ -224,6 +224,11 @@ ${KERNEL_SRC}/README ${KERNEL_CFG_ORG}: ${KERNEL_SRC_SUBMODULE} | submodules cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-1000380-ALSA-timer-Fix-race-between-read-and-ioctl.patch cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-7346-drm-vmwgfx-limit-the-number-of-mip-levels-in-vmw_gb_.patch cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-9605-drm-vmwgfx-Make-sure-backup_handle-is-always-valid.patch + cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-1000364-mm-mmap.c-do-not-blow-on-PROT_NONE-MAP_FIXED-holes-i.patch + cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-1000364-mm-mmap.c-expand_downwards-don-t-require-the-gap-if-.patch + cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-1000365-fs-exec.c-account-for-argv-envp-pointers.patch + cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-10810-drm-virtio-don-t-leak-bo-on-drm_gem_object_init-fail.patch + cd ${KERNEL_SRC}; patch -p1 < ../CVE-2017-7482-rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch sed -i ${KERNEL_SRC}/Makefile -e 's/^EXTRAVERSION.*$$/EXTRAVERSION=${EXTRAVERSION}/' touch $@