Skip to content

Commit e67ae21

Browse files
hdmdaviespcmoore
authored andcommitted
ipv6: Add ipv6_renew_options_kern() that accepts a kernel mem pointer.
The functionality is equivalent to ipv6_renew_options() except that the newopt pointer is in kernel, not user, memory The kernel memory implementation will be used by the CALIPSO network labelling engine, which needs to be able to set IPv6 hop-by-hop options. Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
1 parent d7cce01 commit e67ae21

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

include/net/ipv6.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,12 @@ struct ipv6_txoptions *ipv6_renew_options(struct sock *sk,
308308
int newtype,
309309
struct ipv6_opt_hdr __user *newopt,
310310
int newoptlen);
311+
struct ipv6_txoptions *
312+
ipv6_renew_options_kern(struct sock *sk,
313+
struct ipv6_txoptions *opt,
314+
int newtype,
315+
struct ipv6_opt_hdr *newopt,
316+
int newoptlen);
311317
struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
312318
struct ipv6_txoptions *opt);
313319

net/ipv6/exthdrs.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,27 @@ static int ipv6_renew_option(void *ohdr,
758758
return 0;
759759
}
760760

761+
/**
762+
* ipv6_renew_options - replace a specific ext hdr with a new one.
763+
*
764+
* @sk: sock from which to allocate memory
765+
* @opt: original options
766+
* @newtype: option type to replace in @opt
767+
* @newopt: new option of type @newtype to replace (user-mem)
768+
* @newoptlen: length of @newopt
769+
*
770+
* Returns a new set of options which is a copy of @opt with the
771+
* option type @newtype replaced with @newopt.
772+
*
773+
* @opt may be NULL, in which case a new set of options is returned
774+
* containing just @newopt.
775+
*
776+
* @newopt may be NULL, in which case the specified option type is
777+
* not copied into the new set of options.
778+
*
779+
* The new set of options is allocated from the socket option memory
780+
* buffer of @sk.
781+
*/
761782
struct ipv6_txoptions *
762783
ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
763784
int newtype,
@@ -830,6 +851,34 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
830851
return ERR_PTR(err);
831852
}
832853

854+
/**
855+
* ipv6_renew_options_kern - replace a specific ext hdr with a new one.
856+
*
857+
* @sk: sock from which to allocate memory
858+
* @opt: original options
859+
* @newtype: option type to replace in @opt
860+
* @newopt: new option of type @newtype to replace (kernel-mem)
861+
* @newoptlen: length of @newopt
862+
*
863+
* See ipv6_renew_options(). The difference is that @newopt is
864+
* kernel memory, rather than user memory.
865+
*/
866+
struct ipv6_txoptions *
867+
ipv6_renew_options_kern(struct sock *sk, struct ipv6_txoptions *opt,
868+
int newtype, struct ipv6_opt_hdr *newopt,
869+
int newoptlen)
870+
{
871+
struct ipv6_txoptions *ret_val;
872+
const mm_segment_t old_fs = get_fs();
873+
874+
set_fs(KERNEL_DS);
875+
ret_val = ipv6_renew_options(sk, opt, newtype,
876+
(struct ipv6_opt_hdr __user *)newopt,
877+
newoptlen);
878+
set_fs(old_fs);
879+
return ret_val;
880+
}
881+
833882
struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
834883
struct ipv6_txoptions *opt)
835884
{

0 commit comments

Comments
 (0)