On morello architecture, use of kernel pointers in the uapi structures is not permitted, due to different alignment requirements. Modify these to be __nf_kptr_t.
Signed-off-by: Joshua Lant joshualant@gmail.com --- include/uapi/linux/netfilter/xt_IDLETIMER.h | 6 +- net/netfilter/xt_IDLETIMER.c | 139 ++++++++++---------- 2 files changed, 77 insertions(+), 68 deletions(-)
diff --git a/include/uapi/linux/netfilter/xt_IDLETIMER.h b/include/uapi/linux/netfilter/xt_IDLETIMER.h index 7bfb31a66fc9..5094073607f6 100644 --- a/include/uapi/linux/netfilter/xt_IDLETIMER.h +++ b/include/uapi/linux/netfilter/xt_IDLETIMER.h @@ -25,7 +25,8 @@ struct idletimer_tg_info { char label[MAX_IDLETIMER_LABEL_SIZE];
/* for kernel module internal use only */ - struct idletimer_tg *timer __attribute__((aligned(8))); + /* corresponds to the idletimer_tg struct */ + __nf_kptr_t timer __attribute__((aligned(8))); };
struct idletimer_tg_info_v1 { @@ -37,6 +38,7 @@ struct idletimer_tg_info_v1 { __u8 timer_type;
/* for kernel module internal use only */ - struct idletimer_tg *timer __attribute__((aligned(8))); + /* corresponds to the idletimer_tg struct */ + __nf_kptr_t timer __attribute__((aligned(8))); }; #endif diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c index db720efa811d..7140e45b65bd 100644 --- a/net/netfilter/xt_IDLETIMER.c +++ b/net/netfilter/xt_IDLETIMER.c @@ -136,8 +136,9 @@ static int idletimer_check_sysfs_name(const char *name, unsigned int size) static int idletimer_tg_create(struct idletimer_tg_info *info) { int ret; + struct idletimer_tg *timer_local = (struct idletimer_tg *)info->timer;
- info->timer = kzalloc(sizeof(*info->timer), GFP_KERNEL); + info->timer = (__nf_kptr_t) kzalloc(sizeof(struct idletimer_tg), GFP_KERNEL); if (!info->timer) { ret = -ENOMEM; goto out; @@ -148,36 +149,36 @@ static int idletimer_tg_create(struct idletimer_tg_info *info) goto out_free_timer;
sysfs_attr_init(&info->timer->attr.attr); - info->timer->attr.attr.name = kstrdup(info->label, GFP_KERNEL); - if (!info->timer->attr.attr.name) { + (timer_localinfo->timer)->attr.attr.name = kstrdup(info->label, GFP_KERNEL); + if (!timer_local->attr.attr.name) { ret = -ENOMEM; goto out_free_timer; } - info->timer->attr.attr.mode = 0444; - info->timer->attr.show = idletimer_tg_show; + timer_local->attr.attr.mode = 0444; + timer_local->attr.show = idletimer_tg_show;
- ret = sysfs_create_file(idletimer_tg_kobj, &info->timer->attr.attr); + ret = sysfs_create_file(idletimer_tg_kobj, &timer_local->attr.attr); if (ret < 0) { pr_debug("couldn't add file to sysfs"); goto out_free_attr; }
- list_add(&info->timer->entry, &idletimer_tg_list); + list_add(&timer_local->entry, &idletimer_tg_list);
- timer_setup(&info->timer->timer, idletimer_tg_expired, 0); - info->timer->refcnt = 1; + timer_setup(&timer_local->timer, idletimer_tg_expired, 0); + timer_local->refcnt = 1;
- INIT_WORK(&info->timer->work, idletimer_tg_work); + INIT_WORK(&timer_local->work, idletimer_tg_work);
- mod_timer(&info->timer->timer, + mod_timer(&timer_local->timer, msecs_to_jiffies(info->timeout * 1000) + jiffies);
return 0;
out_free_attr: - kfree(info->timer->attr.attr.name); + kfree(timer_local->attr.attr.name); out_free_timer: - kfree(info->timer); + kfree(timer_local); out: return ret; } @@ -185,8 +186,9 @@ static int idletimer_tg_create(struct idletimer_tg_info *info) static int idletimer_tg_create_v1(struct idletimer_tg_info_v1 *info) { int ret; + struct idletimer_tg *timer_local = (struct idletimer_tg *)info->timer;
- info->timer = kmalloc(sizeof(*info->timer), GFP_KERNEL); + info->timer = (__nf_kptr_t) kmalloc(sizeof(struct idletimer_tg), GFP_KERNEL); if (!info->timer) { ret = -ENOMEM; goto out; @@ -196,16 +198,16 @@ static int idletimer_tg_create_v1(struct idletimer_tg_info_v1 *info) if (ret < 0) goto out_free_timer;
- sysfs_attr_init(&info->timer->attr.attr); - info->timer->attr.attr.name = kstrdup(info->label, GFP_KERNEL); - if (!info->timer->attr.attr.name) { + sysfs_attr_init(&timer_local->attr.attr); + timer_local->attr.attr.name = kstrdup(info->label, GFP_KERNEL); + if (!timer_local->attr.attr.name) { ret = -ENOMEM; goto out_free_timer; } - info->timer->attr.attr.mode = 0444; - info->timer->attr.show = idletimer_tg_show; + timer_local->attr.attr.mode = 0444; + timer_local->attr.show = idletimer_tg_show;
- ret = sysfs_create_file(idletimer_tg_kobj, &info->timer->attr.attr); + ret = sysfs_create_file(idletimer_tg_kobj, &timer_local->attr.attr); if (ret < 0) { pr_debug("couldn't add file to sysfs"); goto out_free_attr; @@ -214,32 +216,32 @@ static int idletimer_tg_create_v1(struct idletimer_tg_info_v1 *info) /* notify userspace */ kobject_uevent(idletimer_tg_kobj,KOBJ_ADD);
- list_add(&info->timer->entry, &idletimer_tg_list); + list_add(&timer_local->entry, &idletimer_tg_list); pr_debug("timer type value is %u", info->timer_type); - info->timer->timer_type = info->timer_type; - info->timer->refcnt = 1; + timer_local->timer_type = info->timer_type; + timer_local->refcnt = 1;
- INIT_WORK(&info->timer->work, idletimer_tg_work); + INIT_WORK(&timer_local->work, idletimer_tg_work);
- if (info->timer->timer_type & XT_IDLETIMER_ALARM) { + if (timer_local->timer_type & XT_IDLETIMER_ALARM) { ktime_t tout; - alarm_init(&info->timer->alarm, ALARM_BOOTTIME, + alarm_init(&timer_local->alarm, ALARM_BOOTTIME, idletimer_tg_alarmproc); - info->timer->alarm.data = info->timer; + timer_local->alarm.data = timer_local; tout = ktime_set(info->timeout, 0); - alarm_start_relative(&info->timer->alarm, tout); + alarm_start_relative(&timer_local->alarm, tout); } else { - timer_setup(&info->timer->timer, idletimer_tg_expired, 0); - mod_timer(&info->timer->timer, + timer_setup(&timer_local->timer, idletimer_tg_expired, 0); + mod_timer(&timer_local->timer, msecs_to_jiffies(info->timeout * 1000) + jiffies); }
return 0;
out_free_attr: - kfree(info->timer->attr.attr.name); + kfree(timer_local->attr.attr.name); out_free_timer: - kfree(info->timer); + kfree(timer_local); out: return ret; } @@ -255,7 +257,7 @@ static unsigned int idletimer_tg_target(struct sk_buff *skb, pr_debug("resetting timer %s, timeout period %u\n", info->label, info->timeout);
- mod_timer(&info->timer->timer, + mod_timer(&((struct idletimer_tg *)info->timer)->timer, msecs_to_jiffies(info->timeout * 1000) + jiffies);
return XT_CONTINUE; @@ -268,15 +270,16 @@ static unsigned int idletimer_tg_target_v1(struct sk_buff *skb, const struct xt_action_param *par) { const struct idletimer_tg_info_v1 *info = par->targinfo; + struct idletimer_tg *timer_local = (struct idletimer_tg *)info->timer;
pr_debug("resetting timer %s, timeout period %u\n", info->label, info->timeout);
- if (info->timer->timer_type & XT_IDLETIMER_ALARM) { + if (timer_local->timer_type & XT_IDLETIMER_ALARM) { ktime_t tout = ktime_set(info->timeout, 0); - alarm_start_relative(&info->timer->alarm, tout); + alarm_start_relative(&timer_local->alarm, tout); } else { - mod_timer(&info->timer->timer, + mod_timer(&timer_local->timer, msecs_to_jiffies(info->timeout * 1000) + jiffies); }
@@ -307,6 +310,7 @@ static int idletimer_tg_checkentry(const struct xt_tgchk_param *par) { struct idletimer_tg_info *info = par->targinfo; int ret; + struct idletimer_tg *timer_local = (struct idletimer_tg *)info->timer;
pr_debug("checkentry targinfo%s\n", info->label);
@@ -318,14 +322,14 @@ static int idletimer_tg_checkentry(const struct xt_tgchk_param *par) } mutex_lock(&list_mutex);
- info->timer = __idletimer_tg_find_by_label(info->label); - if (info->timer) { - info->timer->refcnt++; - mod_timer(&info->timer->timer, + info->timer = (__nf_kptr_t) __idletimer_tg_find_by_label(info->label); + if (timer_local) { + timer_local->refcnt++; + mod_timer(&timer_local->timer, msecs_to_jiffies(info->timeout * 1000) + jiffies);
pr_debug("increased refcnt of timer %s to %u\n", - info->label, info->timer->refcnt); + info->label, timer_local->refcnt); } else { ret = idletimer_tg_create(info); if (ret < 0) { @@ -343,6 +347,7 @@ static int idletimer_tg_checkentry_v1(const struct xt_tgchk_param *par) { struct idletimer_tg_info_v1 *info = par->targinfo; int ret; + struct idletimer_tg *timer_local = (struct idletimer_tg *)info->timer;
pr_debug("checkentry targinfo%s\n", info->label);
@@ -363,31 +368,31 @@ static int idletimer_tg_checkentry_v1(const struct xt_tgchk_param *par)
mutex_lock(&list_mutex);
- info->timer = __idletimer_tg_find_by_label(info->label); + info->timer = (__nf_kptr_t) __idletimer_tg_find_by_label(info->label); if (info->timer) { - if (info->timer->timer_type != info->timer_type) { + if (timer_local->timer_type != info->timer_type) { pr_debug("Adding/Replacing rule with same label and different timer type is not allowed\n"); mutex_unlock(&list_mutex); return -EINVAL; }
- info->timer->refcnt++; + timer_local->refcnt++; if (info->timer_type & XT_IDLETIMER_ALARM) { /* calculate remaining expiry time */ - ktime_t tout = alarm_expires_remaining(&info->timer->alarm); + ktime_t tout = alarm_expires_remaining(&timer_local->alarm); struct timespec64 ktimespec = ktime_to_timespec64(tout);
if (ktimespec.tv_sec > 0) { pr_debug("time_expiry_remaining %lld\n", ktimespec.tv_sec); - alarm_start_relative(&info->timer->alarm, tout); + alarm_start_relative(&timer_local->alarm, tout); } } else { - mod_timer(&info->timer->timer, + mod_timer(&timer_local->timer, msecs_to_jiffies(info->timeout * 1000) + jiffies); } pr_debug("increased refcnt of timer %s to %u\n", - info->label, info->timer->refcnt); + info->label, timer_local->refcnt); } else { ret = idletimer_tg_create_v1(info); if (ret < 0) { @@ -404,23 +409,24 @@ static int idletimer_tg_checkentry_v1(const struct xt_tgchk_param *par) static void idletimer_tg_destroy(const struct xt_tgdtor_param *par) { const struct idletimer_tg_info *info = par->targinfo; + struct idletimer_tg *timer_local = (struct idletimer_tg *)info->timer;
pr_debug("destroy targinfo %s\n", info->label);
mutex_lock(&list_mutex);
- if (--info->timer->refcnt == 0) { + if (--timer_local->refcnt == 0) { pr_debug("deleting timer %s\n", info->label);
- list_del(&info->timer->entry); - timer_shutdown_sync(&info->timer->timer); - cancel_work_sync(&info->timer->work); - sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr); - kfree(info->timer->attr.attr.name); - kfree(info->timer); + list_del(&timer_local->entry); + timer_shutdown_sync(&timer_local->timer); + cancel_work_sync(&timer_local->work); + sysfs_remove_file(idletimer_tg_kobj, &timer_local->attr.attr); + kfree(timer_local->attr.attr.name); + kfree(timer_local); } else { pr_debug("decreased refcnt of timer %s to %u\n", - info->label, info->timer->refcnt); + info->label, timer_local->refcnt); }
mutex_unlock(&list_mutex); @@ -429,27 +435,28 @@ static void idletimer_tg_destroy(const struct xt_tgdtor_param *par) static void idletimer_tg_destroy_v1(const struct xt_tgdtor_param *par) { const struct idletimer_tg_info_v1 *info = par->targinfo; + struct idletimer_tg *timer_local = (struct idletimer_tg *)info->timer;
pr_debug("destroy targinfo %s\n", info->label);
mutex_lock(&list_mutex);
- if (--info->timer->refcnt == 0) { + if (--timer_local->refcnt == 0) { pr_debug("deleting timer %s\n", info->label);
- list_del(&info->timer->entry); - if (info->timer->timer_type & XT_IDLETIMER_ALARM) { - alarm_cancel(&info->timer->alarm); + list_del(&timer_local->entry); + if (timer_local->timer_type & XT_IDLETIMER_ALARM) { + alarm_cancel(&timer_local->alarm); } else { - timer_shutdown_sync(&info->timer->timer); + timer_shutdown_sync(&timer_local->timer); } - cancel_work_sync(&info->timer->work); - sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr); - kfree(info->timer->attr.attr.name); - kfree(info->timer); + cancel_work_sync(&timer_local->work); + sysfs_remove_file(idletimer_tg_kobj, &timer_local->attr.attr); + kfree(timer_local->attr.attr.name); + kfree(timer_local); } else { pr_debug("decreased refcnt of timer %s to %u\n", - info->label, info->timer->refcnt); + info->label, timer_local->refcnt); }
mutex_unlock(&list_mutex);