Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiroslav Benes <mbenes@suse.cz>2014-11-03 16:56:31 +0100
committerMiroslav Benes <mbenes@suse.cz>2014-11-03 16:56:31 +0100
commit600de9d1b7e8d37eb86a58011159f32eb7aedd2f (patch)
tree69b7701fc75d583006c48e468b0eaf9b7ff20666
Initial commit
Signed-off-by: Miroslav Benes <mbenes@suse.cz>
-rw-r--r--Makefile13
-rw-r--r--kgr_patch_main.c39
-rw-r--r--rpm/kgraft-patch.changes5
-rw-r--r--rpm/kgraft-patch.spec59
-rwxr-xr-xscripts/release-version.sh3
-rwxr-xr-xscripts/tar-up.sh55
-rw-r--r--uname_patch/kgr_patch_uname.c125
-rw-r--r--uname_patch/kgr_patch_uname.h9
8 files changed, 308 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..9bfca51
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+KDIR ?= /lib/modules/`uname -r`/build
+
+subdir-ccflags-y := -DDEBUG
+
+obj-m := kgraft-patch-@@RPMRELEASE@@.o
+
+kgraft-patch-@@RPMRELEASE@@-y := kgr_patch_main.o uname_patch/kgr_patch_uname.o
+
+default:
+ $(MAKE) -C $(KDIR) M=$(PWD) modules
+
+clean:
+ $(MAKE) -C $(KDIR) M=$(PWD) clean
diff --git a/kgr_patch_main.c b/kgr_patch_main.c
new file mode 100644
index 0000000..9511ac3
--- /dev/null
+++ b/kgr_patch_main.c
@@ -0,0 +1,39 @@
+#include <linux/kgraft.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include "uname_patch/kgr_patch_uname.h"
+
+static struct kgr_patch patch = {
+ .name = "kgraft-patch-@@RELEASE@@",
+ .owner = THIS_MODULE,
+ .patches = {
+ KGR_PATCH(SyS_newuname, kgr_sys_newuname, true),
+ KGR_PATCH_END
+ }
+};
+
+static int __init kgr_patch_init(void)
+{
+ int retval;
+
+ pr_info("kgraft-patch: initializing\n");
+
+ retval = kgr_patch_uname_init();
+ if (retval)
+ return retval;
+
+ return kgr_patch_kernel(&patch);
+}
+
+static void __exit kgr_patch_cleanup(void)
+{
+ pr_info("kgraft-patch: removed\n");
+
+ kgr_patch_remove(&patch);
+}
+
+module_init(kgr_patch_init);
+module_exit(kgr_patch_cleanup);
+
+MODULE_LICENSE("GPL");
diff --git a/rpm/kgraft-patch.changes b/rpm/kgraft-patch.changes
new file mode 100644
index 0000000..c03b00b
--- /dev/null
+++ b/rpm/kgraft-patch.changes
@@ -0,0 +1,5 @@
+-------------------------------------------------------------------
+Mon Nov 3 13:37:39 UTC 2014 - mbenes@suse.com
+
+- Package with initial kGraft patch (uname)
+
diff --git a/rpm/kgraft-patch.spec b/rpm/kgraft-patch.spec
new file mode 100644
index 0000000..91047c3
--- /dev/null
+++ b/rpm/kgraft-patch.spec
@@ -0,0 +1,59 @@
+#
+# spec file for package kGraft patch module
+#
+# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
+#
+# All modifications and additions to the file contributed by third parties
+# remain the property of their copyright owners, unless otherwise agreed
+# upon. The license for this file, and modifications and additions to the
+# file, is the same license as for the pristine package itself (unless the
+# license for the pristine package is not an Open Source License, in which
+# case the license is the MIT License). An "Open Source License" is a
+# license that conforms to the Open Source Definition (Version 1.9)
+# published by the Open Source Initiative.
+
+# Please submit bugfixes or comments via http://bugs.opensuse.org/
+#
+
+# needssslcertforbuild
+
+Name: kgraft-patch-@@RELEASE@@
+Version: 1
+Release: 1
+%define module_num %(echo %release | sed 'y/\./_/')
+License: GPL-2.0
+Summary: Kgraft patch module
+Group: System/Kernel
+Source0: uname_patch.tar.bz2
+Source1: Makefile
+Source2: kgr_patch_main.c
+BuildRequires: kernel-syms kgraft-devel
+ExclusiveArch: s390x x86_64
+%kgraft_module_package
+
+%description
+This is an initial kGraft patch.
+
+%prep
+%setup -c
+cp %_sourcedir/kgr_patch_main.c .
+cp %_sourcedir/Makefile .
+
+%build
+set -- *
+sed -i 's/@@RPMRELEASE@@/%module_num/g' Makefile
+for flavor in %flavors_to_build; do
+ mkdir -p "obj/$flavor"
+ cp -r "$@" "obj/$flavor"
+ make -C %{kernel_source $flavor} M="$PWD/obj/$flavor" modules
+done
+
+%install
+export INSTALL_MOD_DIR=kgraft
+export INSTALL_MOD_PATH=%buildroot
+for flavor in %flavors_to_build; do
+ make -C %{kernel_source $flavor} M="$PWD/obj/$flavor" modules_install
+done
+
+%changelog
+
diff --git a/scripts/release-version.sh b/scripts/release-version.sh
new file mode 100755
index 0000000..5938dde
--- /dev/null
+++ b/scripts/release-version.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+RELEASE=3_12_28-4
diff --git a/scripts/tar-up.sh b/scripts/tar-up.sh
new file mode 100755
index 0000000..c13e33f
--- /dev/null
+++ b/scripts/tar-up.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+until [ "$#" = "0" ] ; do
+ case "$1" in
+ --dir=*)
+ build_dir=${1#*=}
+ shift
+ ;;
+ -d|--dir)
+ build_dir=$2
+ shift 2
+ ;;
+ -h|--help|-v|--version)
+ cat <<EOF
+
+${0##*/} prepares a kGraft module package for submission into build service
+
+these options are recognized:
+ -d, --dir=DIR create package in DIR instead of default kgraft-mod-source
+
+EOF
+ exit 1
+ ;;
+ *)
+ echo "unknown option '$1'" >&2
+ exit 1
+ ;;
+ esac
+done
+
+[ -z "$build_dir" ] && build_dir=kgraft-mod-source
+if [ -z "$build_dir" ]; then
+ echo "Please define the build directory with the --dir option" >&2
+ exit 1
+fi
+
+rm -f "$build_dir"/*
+mkdir -p "$build_dir"
+
+# eventual TODO: make it more general
+archives="uname_patch"
+for archive in $archives; do
+ echo "$archive.tar.bz2"
+ tar cfj $build_dir/$archive.tar.bz2 $archive
+done
+
+source $(dirname $0)/release-version.sh
+
+install -m 644 kgr_patch_main.c $build_dir
+install -m 644 Makefile $build_dir
+install -m 644 rpm/kgraft-patch.spec $build_dir/kgraft-patch-"$RELEASE".spec
+install -m 644 rpm/kgraft-patch.changes $build_dir/kgraft-patch-"$RELEASE".changes
+
+sed -i "s/@@RELEASE@@/$RELEASE/g" $build_dir/kgr_patch_main.c \
+ $build_dir/kgraft-patch-"$RELEASE".spec
diff --git a/uname_patch/kgr_patch_uname.c b/uname_patch/kgr_patch_uname.c
new file mode 100644
index 0000000..9a20a34
--- /dev/null
+++ b/uname_patch/kgr_patch_uname.c
@@ -0,0 +1,125 @@
+/*
+ * kgraft_patch -- initial SLE Live Patching patch
+ *
+ * Patch uname to show kGraft in version string
+ *
+ * Copyright (c) 2014 SUSE
+ * Author: Libor Pechacek
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/syscalls.h>
+#include <linux/personality.h>
+#include <linux/utsname.h>
+#include <generated/utsrelease.h>
+#include <linux/version.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <asm/uaccess.h>
+
+#ifdef COMPAT_UTS_MACHINE
+#define override_architecture(name) \
+ (personality(current->personality) == PER_LINUX32 && \
+ copy_to_user(name->machine, COMPAT_UTS_MACHINE, \
+ sizeof(COMPAT_UTS_MACHINE)))
+#else
+#define override_architecture(name) 0
+#endif
+
+/*
+ * Work around broken programs that cannot handle "Linux 3.0".
+ * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40
+ */
+static int override_release(char __user *release, size_t len)
+{
+ int ret = 0;
+
+ if (current->personality & UNAME26) {
+ const char *rest = UTS_RELEASE;
+ char buf[65] = { 0 };
+ int ndots = 0;
+ unsigned v;
+ size_t copy;
+
+ while (*rest) {
+ if (*rest == '.' && ++ndots >= 3)
+ break;
+ if (!isdigit(*rest) && *rest != '.')
+ break;
+ rest++;
+ }
+ v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40;
+ copy = clamp_t(size_t, len, 1, sizeof(buf));
+ copy = scnprintf(buf, copy, "2.6.%u%s", v, rest);
+ ret = copy_to_user(release, buf, copy + 1);
+ }
+ return ret;
+}
+
+#define KGR_TAG "/kGraft"
+
+static struct rw_semaphore *kgr_uts_sem;
+
+static int override_version(char __user *version, size_t len, char *kgr_version)
+{
+ int ret = 0;
+ char *right_brace;
+ size_t newlen;
+
+ newlen = strlen(kgr_version) + strlen(KGR_TAG);
+ if (newlen >= len) {
+ WARN_ONCE(1, "kgraft-patch: not enough space for utsname.version extension");
+ goto out;
+ }
+
+ right_brace = strchr(kgr_version, ')');
+ if (!right_brace) {
+ WARN_ONCE(1, "kgraft-patch: did not find the commit id");
+ goto out;
+ }
+
+ memmove(right_brace + strlen(KGR_TAG), right_brace,
+ strlen(right_brace) + 1);
+ memcpy(right_brace, KGR_TAG, strlen(KGR_TAG));
+
+ ret = copy_to_user(version, kgr_version, newlen + 1);
+
+out:
+ return ret;
+}
+
+asmlinkage long kgr_sys_newuname(struct new_utsname __user *name)
+{
+ int errno = 0;
+ char kgr_version[65] = { 0 };
+
+ down_read(kgr_uts_sem);
+ if (copy_to_user(name, utsname(), sizeof *name))
+ errno = -EFAULT;
+ memcpy(kgr_version, utsname()->version, sizeof(utsname()->version));
+ up_read(kgr_uts_sem);
+
+ if (!errno && override_release(name->release, sizeof(name->release)))
+ errno = -EFAULT;
+ if (!errno && override_architecture(name))
+ errno = -EFAULT;
+ if (!errno && override_version(name->version, sizeof(name->version),
+ kgr_version))
+ errno = -EFAULT;
+ return errno;
+}
+
+int kgr_patch_uname_init(void)
+{
+ unsigned long addr;
+
+ addr = kallsyms_lookup_name("uts_sem");
+ if (!addr) {
+ pr_err("kgraft-patch: symbol uts_sem not resolved\n");
+ return -EFAULT;
+ }
+ kgr_uts_sem = (struct rw_semaphore *) addr;
+
+ return 0;
+}
diff --git a/uname_patch/kgr_patch_uname.h b/uname_patch/kgr_patch_uname.h
new file mode 100644
index 0000000..d6625e3
--- /dev/null
+++ b/uname_patch/kgr_patch_uname.h
@@ -0,0 +1,9 @@
+#ifndef _KGR_PATCH_UNAME_H
+#define _KGR_PATCH_UNAME_H
+
+#include <linux/utsname.h>
+
+extern int kgr_patch_uname_init(void);
+extern asmlinkage long kgr_sys_newuname(struct new_utsname __user *name);
+
+#endif