]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'encrypted-key-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorJames Morris <jmorris@namei.org>
Fri, 18 Nov 2011 00:17:23 +0000 (11:17 +1100)
committerJames Morris <jmorris@namei.org>
Fri, 18 Nov 2011 00:17:23 +0000 (11:17 +1100)
16 files changed:
arch/s390/Kconfig
arch/s390/crypto/crypt_s390.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/setup.h
arch/s390/include/asm/timex.h
arch/s390/include/asm/unistd.h
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/early.c
arch/s390/kernel/setup.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/topology.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/mm/fault.c
drivers/s390/char/zcore.c
drivers/s390/crypto/ap_bus.c
security/smack/smackfs.c

index a9fbd43395f71814d85a284a63900dc5a7dcc018..373679b3744a7992c7009281c1747b3aeb38157a 100644 (file)
@@ -572,6 +572,7 @@ config KEXEC
 config CRASH_DUMP
        bool "kernel crash dumps"
        depends on 64BIT
+       select KEXEC
        help
          Generate crash dump after being started by kexec.
          Crash dump kernels are loaded in the main kernel with kexec-tools
index 49676771bd66a278e73db7a2430612a57a1cf6a1..ffd1ac255f19444d838e58b2fb2ef2b716b02f77 100644 (file)
@@ -368,9 +368,12 @@ static inline int crypt_s390_func_available(int func,
 
        if (facility_mask & CRYPT_S390_MSA && !test_facility(17))
                return 0;
-       if (facility_mask & CRYPT_S390_MSA3 && !test_facility(76))
+
+       if (facility_mask & CRYPT_S390_MSA3 &&
+           (!test_facility(2) || !test_facility(76)))
                return 0;
-       if (facility_mask & CRYPT_S390_MSA4 && !test_facility(77))
+       if (facility_mask & CRYPT_S390_MSA4 &&
+           (!test_facility(2) || !test_facility(77)))
                return 0;
 
        switch (func & CRYPT_S390_OP_MASK) {
index 34ede0ea85a9d0ae6d03a8c52b3bb3f43cb4e1ac..524d23b8610ceb65c42661a97e79226125dbadf3 100644 (file)
@@ -593,6 +593,8 @@ static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste)
        unsigned long address, bits;
        unsigned char skey;
 
+       if (!pte_present(*ptep))
+               return pgste;
        address = pte_val(*ptep) & PAGE_MASK;
        skey = page_get_storage_key(address);
        bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
@@ -625,6 +627,8 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste)
 #ifdef CONFIG_PGSTE
        int young;
 
+       if (!pte_present(*ptep))
+               return pgste;
        young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK);
        /* Transfer page referenced bit to pte software bit (host view) */
        if (young || (pgste_val(pgste) & RCP_HR_BIT))
@@ -638,13 +642,15 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste)
 
 }
 
-static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste)
+static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry)
 {
 #ifdef CONFIG_PGSTE
        unsigned long address;
        unsigned long okey, nkey;
 
-       address = pte_val(*ptep) & PAGE_MASK;
+       if (!pte_present(entry))
+               return;
+       address = pte_val(entry) & PAGE_MASK;
        okey = nkey = page_get_storage_key(address);
        nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT);
        /* Set page access key and fetch protection bit from pgste */
@@ -712,7 +718,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
 
        if (mm_has_pgste(mm)) {
                pgste = pgste_get_lock(ptep);
-               pgste_set_pte(ptep, pgste);
+               pgste_set_pte(ptep, pgste, entry);
                *ptep = entry;
                pgste_set_unlock(ptep, pgste);
        } else
index 5a099714df0459b9470e3d158e0b163bf8ce770b..097183c70407a81e9147697a37c880a6008b4ed1 100644 (file)
@@ -82,6 +82,7 @@ extern unsigned int user_mode;
 #define MACHINE_FLAG_LPAR      (1UL << 12)
 #define MACHINE_FLAG_SPP       (1UL << 13)
 #define MACHINE_FLAG_TOPOLOGY  (1UL << 14)
+#define MACHINE_FLAG_STCKF     (1UL << 15)
 
 #define MACHINE_IS_VM          (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
 #define MACHINE_IS_KVM         (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -100,6 +101,7 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_PFMF       (0)
 #define MACHINE_HAS_SPP                (0)
 #define MACHINE_HAS_TOPOLOGY   (0)
+#define MACHINE_HAS_STCKF      (0)
 #else /* __s390x__ */
 #define MACHINE_HAS_IEEE       (1)
 #define MACHINE_HAS_CSP                (1)
@@ -111,6 +113,7 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_PFMF       (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
 #define MACHINE_HAS_SPP                (S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
 #define MACHINE_HAS_TOPOLOGY   (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
+#define MACHINE_HAS_STCKF      (S390_lowcore.machine_flags & MACHINE_FLAG_STCKF)
 #endif /* __s390x__ */
 
 #define ZFCPDUMP_HSA_SIZE      (32UL<<20)
index d610bef9c5e91a425ad01a683525f46ba0c055e1..c447a27a7fdb109be95edf0d6884026df6e895ce 100644 (file)
@@ -90,7 +90,7 @@ static inline unsigned long long get_clock_fast(void)
 {
        unsigned long long clk;
 
-       if (test_facility(25))
+       if (MACHINE_HAS_STCKF)
                asm volatile(".insn     s,0xb27c0000,%0" : "=Q" (clk) : : "cc");
        else
                clk = get_clock();
index 404bdb9671b4f5c8d03d2391e93abf26e5b38a59..58de4c91c333358000779b283efdad2de1ebe445 100644 (file)
 #define __NR_clock_adjtime     337
 #define __NR_syncfs            338
 #define __NR_setns             339
-#define NR_syscalls 340
+#define __NR_process_vm_readv  340
+#define __NR_process_vm_writev 341
+#define NR_syscalls 342
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index 5006a1d9f5d0ed6d3abd95f3cca652d87689dcef..18c51df9fe06c5ed98f785fb6af86655c025e887 100644 (file)
@@ -1627,3 +1627,23 @@ ENTRY(sys_setns_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        jg      sys_setns
+
+ENTRY(compat_sys_process_vm_readv_wrapper)
+       lgfr    %r2,%r2                 # compat_pid_t
+       llgtr   %r3,%r3                 # struct compat_iovec __user *
+       llgfr   %r4,%r4                 # unsigned long
+       llgtr   %r5,%r5                 # struct compat_iovec __user *
+       llgfr   %r6,%r6                 # unsigned long
+       llgf    %r0,164(%r15)           # unsigned long
+       stg     %r0,160(%r15)
+       jg      sys_process_vm_readv
+
+ENTRY(compat_sys_process_vm_writev_wrapper)
+       lgfr    %r2,%r2                 # compat_pid_t
+       llgtr   %r3,%r3                 # struct compat_iovec __user *
+       llgfr   %r4,%r4                 # unsigned long
+       llgtr   %r5,%r5                 # struct compat_iovec __user *
+       llgfr   %r6,%r6                 # unsigned long
+       llgf    %r0,164(%r15)           # unsigned long
+       stg     %r0,160(%r15)
+       jg      sys_process_vm_writev
index 37394b3413e2776dfd24586f0578045e488bd054..c9ffe002519715d64ddc16d2a2caafcbf47cb8b2 100644 (file)
@@ -390,6 +390,8 @@ static __init void detect_machine_facilities(void)
                S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
        if (test_facility(40))
                S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;
+       if (test_facility(25))
+               S390_lowcore.machine_flags |= MACHINE_FLAG_STCKF;
 #endif
 }
 
index 8ac6bfa2786cbe139d9964b1f4ab374e4302e2e8..e58a462949b164ea90c5697696b9ccec47bb7ff4 100644 (file)
@@ -211,6 +211,8 @@ static void __init setup_zfcpdump(unsigned int console_devno)
 
        if (ipl_info.type != IPL_TYPE_FCP_DUMP)
                return;
+       if (OLDMEM_BASE)
+               return;
        if (console_devno != -1)
                sprintf(str, " cio_ignore=all,!0.0.%04x,!0.0.%04x",
                        ipl_info.data.fcp.dev_id.devno, console_devno);
@@ -482,7 +484,7 @@ static void __init setup_memory_end(void)
 
 
 #ifdef CONFIG_ZFCPDUMP
-       if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
+       if (ipl_info.type == IPL_TYPE_FCP_DUMP && !OLDMEM_BASE) {
                memory_end = ZFCPDUMP_HSA_SIZE;
                memory_end_set = 1;
        }
index 73eb08c874fb450ef6ba0464d4aa4ca845bb6911..bcab2f04ba581f7648426a1790485d53626d8fda 100644 (file)
@@ -348,3 +348,5 @@ SYSCALL(sys_open_by_handle_at,sys_open_by_handle_at,compat_sys_open_by_handle_at
 SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime_wrapper)
 SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper)
 SYSCALL(sys_setns,sys_setns,sys_setns_wrapper)
+SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */
+SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper)
index 77b8942b9a153af398cf9cf0e2dfd8eb7c5629ef..fdb5b8cb260f683e1f4559f95c006a7838690f60 100644 (file)
@@ -68,8 +68,10 @@ static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
        return mask;
 }
 
-static void add_cpus_to_mask(struct topology_cpu *tl_cpu,
-                            struct mask_info *book, struct mask_info *core)
+static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
+                                         struct mask_info *book,
+                                         struct mask_info *core,
+                                         int z10)
 {
        unsigned int cpu;
 
@@ -88,10 +90,16 @@ static void add_cpus_to_mask(struct topology_cpu *tl_cpu,
                        cpu_book_id[lcpu] = book->id;
 #endif
                        cpumask_set_cpu(lcpu, &core->mask);
-                       cpu_core_id[lcpu] = core->id;
+                       if (z10) {
+                               cpu_core_id[lcpu] = rcpu;
+                               core = core->next;
+                       } else {
+                               cpu_core_id[lcpu] = core->id;
+                       }
                        smp_cpu_polarization[lcpu] = tl_cpu->pp;
                }
        }
+       return core;
 }
 
 static void clear_masks(void)
@@ -123,18 +131,41 @@ static void tl_to_cores(struct sysinfo_15_1_x *info)
 {
 #ifdef CONFIG_SCHED_BOOK
        struct mask_info *book = &book_info;
+       struct cpuid cpu_id;
 #else
        struct mask_info *book = NULL;
 #endif
        struct mask_info *core = &core_info;
        union topology_entry *tle, *end;
+       int z10 = 0;
 
-
+#ifdef CONFIG_SCHED_BOOK
+       get_cpu_id(&cpu_id);
+       z10 = cpu_id.machine == 0x2097 || cpu_id.machine == 0x2098;
+#endif
        spin_lock_irq(&topology_lock);
        clear_masks();
        tle = info->tle;
        end = (union topology_entry *)((unsigned long)info + info->length);
        while (tle < end) {
+#ifdef CONFIG_SCHED_BOOK
+               if (z10) {
+                       switch (tle->nl) {
+                       case 1:
+                               book = book->next;
+                               book->id = tle->container.id;
+                               break;
+                       case 0:
+                               core = add_cpus_to_mask(&tle->cpu, book, core, z10);
+                               break;
+                       default:
+                               clear_masks();
+                               goto out;
+                       }
+                       tle = next_tle(tle);
+                       continue;
+               }
+#endif
                switch (tle->nl) {
 #ifdef CONFIG_SCHED_BOOK
                case 2:
@@ -147,7 +178,7 @@ static void tl_to_cores(struct sysinfo_15_1_x *info)
                        core->id = tle->container.id;
                        break;
                case 0:
-                       add_cpus_to_mask(&tle->cpu, book, core);
+                       add_cpus_to_mask(&tle->cpu, book, core, z10);
                        break;
                default:
                        clear_masks();
@@ -328,8 +359,8 @@ void __init s390_init_cpu_topology(void)
        for (i = 0; i < TOPOLOGY_NR_MAG; i++)
                printk(" %d", info->mag[i]);
        printk(" / %d\n", info->mnest);
-       alloc_masks(info, &core_info, 2);
+       alloc_masks(info, &core_info, 1);
 #ifdef CONFIG_SCHED_BOOK
-       alloc_masks(info, &book_info, 3);
+       alloc_masks(info, &book_info, 2);
 #endif
 }
index 56fe6bc81fee45804a61c37fb189ccf73a0b72e8..e4c79ebb40e628850fd230fc94a0c7fdc77aaeb1 100644 (file)
@@ -43,6 +43,8 @@ SECTIONS
 
        NOTES :text :note
 
+       .dummy : { *(.dummy) } :data
+
        RODATA
 
 #ifdef CONFIG_SHARED_KERNEL
index 1766def5bc3fc7f4717904313c69b2a7879b6d86..a9a301866b3c1846f37792aa371620e2b3004415 100644 (file)
@@ -587,8 +587,13 @@ static void pfault_interrupt(unsigned int ext_int_code,
                } else {
                        /* Completion interrupt was faster than initial
                         * interrupt. Set pfault_wait to -1 so the initial
-                        * interrupt doesn't put the task to sleep. */
-                       tsk->thread.pfault_wait = -1;
+                        * interrupt doesn't put the task to sleep.
+                        * If the task is not running, ignore the completion
+                        * interrupt since it must be a leftover of a PFAULT
+                        * CANCEL operation which didn't remove all pending
+                        * completion interrupts. */
+                       if (tsk->state == TASK_RUNNING)
+                               tsk->thread.pfault_wait = -1;
                }
                put_task_struct(tsk);
        } else {
index 43068fbd0baacfe8beb7d353cda35a8c06c371e2..1b6d9247fdc78a4237d5e7048347a0a66875d140 100644 (file)
@@ -641,6 +641,8 @@ static int __init zcore_init(void)
 
        if (ipl_info.type != IPL_TYPE_FCP_DUMP)
                return -ENODATA;
+       if (OLDMEM_BASE)
+               return -ENODATA;
 
        zcore_dbf = debug_register("zcore", 4, 1, 4 * sizeof(long));
        debug_register_view(zcore_dbf, &debug_sprintf_view);
index b77ae519d79c4eea8c6d87a1e08609dc70ae0276..ec94f049e99543849ed56c90c665102c40c5b87e 100644 (file)
@@ -1271,18 +1271,16 @@ ap_config_timeout(unsigned long ptr)
 }
 
 /**
- * ap_schedule_poll_timer(): Schedule poll timer.
+ * __ap_schedule_poll_timer(): Schedule poll timer.
  *
  * Set up the timer to run the poll tasklet
  */
-static inline void ap_schedule_poll_timer(void)
+static inline void __ap_schedule_poll_timer(void)
 {
        ktime_t hr_time;
 
        spin_lock_bh(&ap_poll_timer_lock);
-       if (ap_using_interrupts() || ap_suspend_flag)
-               goto out;
-       if (hrtimer_is_queued(&ap_poll_timer))
+       if (hrtimer_is_queued(&ap_poll_timer) || ap_suspend_flag)
                goto out;
        if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
                hr_time = ktime_set(0, poll_timeout);
@@ -1293,6 +1291,18 @@ out:
        spin_unlock_bh(&ap_poll_timer_lock);
 }
 
+/**
+ * ap_schedule_poll_timer(): Schedule poll timer.
+ *
+ * Set up the timer to run the poll tasklet
+ */
+static inline void ap_schedule_poll_timer(void)
+{
+       if (ap_using_interrupts())
+               return;
+       __ap_schedule_poll_timer();
+}
+
 /**
  * ap_poll_read(): Receive pending reply messages from an AP device.
  * @ap_dev: pointer to the AP device
@@ -1374,8 +1384,9 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
                        *flags |= 1;
                *flags |= 2;
                break;
-       case AP_RESPONSE_Q_FULL:
        case AP_RESPONSE_RESET_IN_PROGRESS:
+               __ap_schedule_poll_timer();
+       case AP_RESPONSE_Q_FULL:
                *flags |= 2;
                break;
        case AP_RESPONSE_MESSAGE_TOO_BIG:
index 6aceef518a41fe7cd095bf8f860afe210abeb6ce..5c32f36ff70618dfb08e3040c94060238dfa44da 100644 (file)
@@ -102,9 +102,6 @@ static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
 
 const char *smack_cipso_option = SMACK_CIPSO_OPTION;
 
-
-#define        SEQ_READ_FINISHED       ((loff_t)-1)
-
 /*
  * Values for parsing cipso rules
  * SMK_DIGITLEN: Length of a digit field in a rule.
@@ -357,10 +354,12 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
 
        rc = count;
        /*
+        * If this is "load" as opposed to "load-self" and a new rule
+        * it needs to get added for reporting.
         * smk_set_access returns true if there was already a rule
         * for the subject/object pair, and false if it was new.
         */
-       if (!smk_set_access(rule, rule_list, rule_lock)) {
+       if (load && !smk_set_access(rule, rule_list, rule_lock)) {
                smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
                if (smlp != NULL) {
                        smlp->smk_rule = rule;
@@ -377,12 +376,12 @@ out:
        return rc;
 }
 
-
 /*
- * Seq_file read operations for /smack/load
+ * Core logic for smackfs seq list operations.
  */
 
-static void *load_seq_start(struct seq_file *s, loff_t *pos)
+static void *smk_seq_start(struct seq_file *s, loff_t *pos,
+                               struct list_head *head)
 {
        struct list_head *list;
 
@@ -390,7 +389,7 @@ static void *load_seq_start(struct seq_file *s, loff_t *pos)
         * This is 0 the first time through.
         */
        if (s->index == 0)
-               s->private = &smack_rule_list;
+               s->private = head;
 
        if (s->private == NULL)
                return NULL;
@@ -404,11 +403,12 @@ static void *load_seq_start(struct seq_file *s, loff_t *pos)
        return list;
 }
 
-static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
+static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
+                               struct list_head *head)
 {
        struct list_head *list = v;
 
-       if (list_is_last(list, &smack_rule_list)) {
+       if (list_is_last(list, head)) {
                s->private = NULL;
                return NULL;
        }
@@ -416,6 +416,25 @@ static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
        return list->next;
 }
 
+static void smk_seq_stop(struct seq_file *s, void *v)
+{
+       /* No-op */
+}
+
+/*
+ * Seq_file read operations for /smack/load
+ */
+
+static void *load_seq_start(struct seq_file *s, loff_t *pos)
+{
+       return smk_seq_start(s, pos, &smack_rule_list);
+}
+
+static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+       return smk_seq_next(s, v, pos, &smack_rule_list);
+}
+
 static int load_seq_show(struct seq_file *s, void *v)
 {
        struct list_head *list = v;
@@ -446,16 +465,11 @@ static int load_seq_show(struct seq_file *s, void *v)
        return 0;
 }
 
-static void load_seq_stop(struct seq_file *s, void *v)
-{
-       /* No-op */
-}
-
 static const struct seq_operations load_seq_ops = {
        .start = load_seq_start,
        .next  = load_seq_next,
        .show  = load_seq_show,
-       .stop  = load_seq_stop,
+       .stop  = smk_seq_stop,
 };
 
 /**
@@ -574,28 +588,12 @@ static void smk_unlbl_ambient(char *oldambient)
 
 static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
 {
-       if (*pos == SEQ_READ_FINISHED)
-               return NULL;
-       if (list_empty(&smack_known_list))
-               return NULL;
-
-       return smack_known_list.next;
+       return smk_seq_start(s, pos, &smack_known_list);
 }
 
 static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-       struct list_head  *list = v;
-
-       /*
-        * labels with no associated cipso value wont be printed
-        * in cipso_seq_show
-        */
-       if (list_is_last(list, &smack_known_list)) {
-               *pos = SEQ_READ_FINISHED;
-               return NULL;
-       }
-
-       return list->next;
+       return smk_seq_next(s, v, pos, &smack_known_list);
 }
 
 /*
@@ -634,16 +632,11 @@ static int cipso_seq_show(struct seq_file *s, void *v)
        return 0;
 }
 
-static void cipso_seq_stop(struct seq_file *s, void *v)
-{
-       /* No-op */
-}
-
 static const struct seq_operations cipso_seq_ops = {
        .start = cipso_seq_start,
-       .stop  = cipso_seq_stop,
        .next  = cipso_seq_next,
        .show  = cipso_seq_show,
+       .stop  = smk_seq_stop,
 };
 
 /**
@@ -788,23 +781,12 @@ static const struct file_operations smk_cipso_ops = {
 
 static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
 {
-       if (*pos == SEQ_READ_FINISHED)
-               return NULL;
-       if (list_empty(&smk_netlbladdr_list))
-               return NULL;
-       return smk_netlbladdr_list.next;
+       return smk_seq_start(s, pos, &smk_netlbladdr_list);
 }
 
 static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-       struct list_head *list = v;
-
-       if (list_is_last(list, &smk_netlbladdr_list)) {
-               *pos = SEQ_READ_FINISHED;
-               return NULL;
-       }
-
-       return list->next;
+       return smk_seq_next(s, v, pos, &smk_netlbladdr_list);
 }
 #define BEBITS (sizeof(__be32) * 8)
 
@@ -828,16 +810,11 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v)
        return 0;
 }
 
-static void netlbladdr_seq_stop(struct seq_file *s, void *v)
-{
-       /* No-op */
-}
-
 static const struct seq_operations netlbladdr_seq_ops = {
        .start = netlbladdr_seq_start,
-       .stop  = netlbladdr_seq_stop,
        .next  = netlbladdr_seq_next,
        .show  = netlbladdr_seq_show,
+       .stop  = smk_seq_stop,
 };
 
 /**
@@ -1405,23 +1382,14 @@ static void *load_self_seq_start(struct seq_file *s, loff_t *pos)
 {
        struct task_smack *tsp = current_security();
 
-       if (*pos == SEQ_READ_FINISHED)
-               return NULL;
-       if (list_empty(&tsp->smk_rules))
-               return NULL;
-       return tsp->smk_rules.next;
+       return smk_seq_start(s, pos, &tsp->smk_rules);
 }
 
 static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
        struct task_smack *tsp = current_security();
-       struct list_head *list = v;
 
-       if (list_is_last(list, &tsp->smk_rules)) {
-               *pos = SEQ_READ_FINISHED;
-               return NULL;
-       }
-       return list->next;
+       return smk_seq_next(s, v, pos, &tsp->smk_rules);
 }
 
 static int load_self_seq_show(struct seq_file *s, void *v)
@@ -1453,16 +1421,11 @@ static int load_self_seq_show(struct seq_file *s, void *v)
        return 0;
 }
 
-static void load_self_seq_stop(struct seq_file *s, void *v)
-{
-       /* No-op */
-}
-
 static const struct seq_operations load_self_seq_ops = {
        .start = load_self_seq_start,
        .next  = load_self_seq_next,
        .show  = load_self_seq_show,
-       .stop  = load_self_seq_stop,
+       .stop  = smk_seq_stop,
 };