sock_i_uid() acquires the sk_callback_lock which does not exist for
sockets in TCP_NEW_SYN_RECV state. This results in errors showing up
as spinlock bad magic. Fix this by looking for the full sock as
suggested by Eric.
Callstack for reference -
-003|rwlock_bug
-004|arch_read_lock
-004|do_raw_read_lock
-005|raw_read_lock_bh
-006|sock_i_uid
-007|from_kuid_munged(inline)
-007|reset_timer
-008|idletimer_tg_target
-009|ipt_do_table
-010|iptable_mangle_hook
-011|nf_iterate
-012|nf_hook_slow
-013|NF_HOOK_COND(inline)
-013|ip_output
-014|ip_local_out
-015|ip_build_and_send_pkt
-016|tcp_v4_send_synack
-017|atomic_sub_return(inline)
-017|reqsk_put(inline)
-017|tcp_conn_request
-018|tcp_v4_conn_request
-019|tcp_rcv_state_process
-020|tcp_v4_do_rcv
-021|tcp_v4_rcv
-022|ip_local_deliver_finish
-023|NF_HOOK_THRESH(inline)
-023|NF_HOOK(inline)
-023|ip_local_deliver
-024|ip_rcv_finish
-025|NF_HOOK_THRESH(inline)
-025|NF_HOOK(inline)
-025|ip_rcv
-026|deliver_skb(inline)
-026|deliver_ptype_list_skb(inline)
-026|__netif_receive_skb_core
-027|__netif_receive_skb
-028|netif_receive_skb_internal
-029|netif_receive_skb
Change-Id: Ic8f3a3d2d7af31434d1163b03971994e2125d552
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Cc: Eric Dumazet <edumazet@google.com>
schedule_work(&timer->work) appears to be called after
cancel_work_sync(&info->timer->work) is completed.
Work can be scheduled from the PM_POST_SUSPEND notification event
even after cancel_work_sync is called.
Call stack
-004|notify_netlink_uevent(
| [X19] timer = 0xFFFFFFC0A5DFC780 -> (
| ...
| [NSD:0xFFFFFFC0A5DFC800] kobj = 0x6B6B6B6B6B6B6B6B,
| [NSD:0xFFFFFFC0A5DFC868] timeout = 0x6B6B6B6B,
| [NSD:0xFFFFFFC0A5DFC86C] refcnt = 0x6B6B6B6B,
| [NSD:0xFFFFFFC0A5DFC870] work_pending = 0x6B,
| [NSD:0xFFFFFFC0A5DFC871] send_nl_msg = 0x6B,
| [NSD:0xFFFFFFC0A5DFC872] active = 0x6B,
| [NSD:0xFFFFFFC0A5DFC874] uid = 0x6B6B6B6B,
| [NSD:0xFFFFFFC0A5DFC878] suspend_time_valid = 0x6B))
-005|idletimer_tg_work(
-006|__read_once_size(inline)
-006|static_key_count(inline)
-006|static_key_false(inline)
-006|trace_workqueue_execute_end(inline)
-006|process_one_work(
-007|worker_thread(
-008|kthread(
-009|ret_from_fork(asm)
---|end of frame
Force any pending idletimer_tg_work() to complete before freeing
the associated work struct and after unregistering to the pm_notifier
callback.
Change-Id: I4c5f0a1c142f7d698c092cf7bcafdb0f9fbaa9c1
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Remove unused variable "ifindex" in rt6_get_route_info().
"ifindex" is not used anymore, dev->ifindex is used directly instead.
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
In upstream commit 7200135bc1e61f1437dc326ae2ef2f310c50b4eb
(netfilter: kill ulog targets)
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7200135bc1e6
ipt_ULOG target was removed, meanwhile, the IP_NF_TARGET_ULOG Kconfig
and ipt_ULOG.h header file were removed too. This causes we cannot enable
QUOTA2_LOG, and netd complains this error: "Unable to open quota socket".
So when we reach the quota2 limit, userspace will not be notified with
this event.
Since IP_NF_TARGET_ULOG was removed, we need not depend on
"IP_NF_TARGET_ULOG=n", and for compatibility, add ulog_packet_msg_t
related definitions copied from "ipt_ULOG.h".
Change-Id: I38132efaabf52bea75dfd736ce734a1b9690e87e
Reported-by: Samboo Shen <samboo.shen@spreadtrum.com>
Signed-off-by: Liping Zhang <liping.zhang@spreadtrum.com>
In an issue very similar to 4e461c777e3 (xt_qtaguid: Fix panic
caused by synack processing), we were seeing panics on occasion
in testing.
In this case, it was the same issue, but caused by a different
call path, as the sk being returned from qtaguid_find_sk() was
not a full socket. Resulting in the sk->sk_socket deref to fail.
This patch adds an extra check to ensure the sk being retuned
is a full socket, and if not it returns NULL.
Reported-by: Milosz Wasilewski <milosz.wasilewski@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
In upstream commit ca6fb06518836ef9b65dc0aac02ff97704d52a05
(tcp: attach SYNACK messages to request sockets instead of
listener)
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=ca6fb0651883
The building of synack messages was changed, which made it so
the skb->sk points to a casted request_sock. This is problematic,
as there is no sk_socket in a request_sock. So when the qtaguid_mt
function tries to access the sk->sk_socket, it accesses uninitialized
memory.
After looking at how other netfilter implementations handle this,
I realized there was a skb_to_full_sk() helper added, which the
xt_qtaguid code isn't yet using.
This patch adds its use, and resovles panics seen when accessing
uninitialzed memory when processing synack packets.
Reported-by: YongQin Liu <yongquin.liu@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Update seq_printf() usage in xt_qtaguid to align
with changes from mainline commit 6798a8caaf64
"fs/seq_file: convert int seq_vprint/seq_printf/etc...
returns to void".
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Since rx_bytes accounting does not include Ethernet Headers in
br_input.c, excluding ETH_HLEN on the transmit path for consistent
measurement of packet length on both the Tx and Rx chains.
The clean way would be for Rx to include the eth header, but the
skb len has already been adjusted by the time the br code sees the skb.
This is only a temporary workaround until we can completely ignore or
cleanly fix the skb->len handling.
Change-Id: I910de95a4686b2119da7f1f326e2154ef31f9972
Signed-off-by: Ashish Sharma <ashishsharma@google.com>
Some platforms do not want to power down rfkill devices on suspend.
Change-Id: I62a11630521c636d54a4a02ab9037a43435925f5
Signed-off-by: Nick Pelly <npelly@google.com>
The default initial rwnd is hardcoded to 10.
Now we allow it to be controlled via
/proc/sys/net/ipv4/tcp_default_init_rwnd
which limits the values from 3 to 100
This is somewhat needed because ipv6 routes are
autoconfigured by the kernel.
See "An Argument for Increasing TCP's Initial Congestion Window"
in https://developers.google.com/speed/articles/tcp_initcwnd_paper.pdf
Change-Id: I386b2a9d62de0ebe05c1ebe1b4bd91b314af5c54
Signed-off-by: JP Abgrall <jpa@google.com>
Conflicts:
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_input.c
Miss a lock protection in if_tag_stat_update while doing get_iface_entry. So if
one CPU is doing iface_stat_create while another CPU is doing if_tag_stat_update,
race will happened.
Change-Id: Ib8d98e542f4e385685499f5b7bb7354f08654a75
Signed-off-by: Liping Zhang <liping.zhang@spreadtrum.com>
Update xt_socket_lookup_slow_v* usage in aosp patches, to
align with changes from mainline commit 686c9b50809d
"netfilter: x_tables: Use par->net instead of computing
from the passed net devices".
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Add missing header <linux/miscdevice.h> and use
xt_socket_lookup_slow_v* instead of xt_socket_get*_sk
in xt_qtaguid.c.
Fix xt_socket_lookup_slow_v* functions in xt_socket.c
and declare them in xt_socket.h
Change-Id: I55819b2d4ffa82a2be20995c87d28fb5cc77b5ba
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
nf_socket_get_sock_v[4|6]() do not always increment sock refcount, which
causes confusion in xt_qtaguid module which is not aware of this fact
and drops the reference whether it should have or not. Fix it by
changing nf_socket_get_sock_v[4|6]() to always increment recount of returned
sock.
This should fix the following crash:
[ 111.319523] BUG: failure at
/mnt/host/source/src/third_party/kernel/v3.18/net/ipv4/inet_timewait_sock.c:90/__inet_twsk_kill()!
[ 111.331192] Kernel panic - not syncing: BUG!
[ 111.335468] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G U W
3.18.0-06867-g268df91 #1
[ 111.343810] Hardware name: Google Tegra210 Smaug Rev 1+ (DT)
[ 111.349463] Call trace:
[ 111.351917] [<ffffffc000207288>] dump_backtrace+0x0/0x10c
[ 111.357314] [<ffffffc0002073a4>] show_stack+0x10/0x1c
[ 111.362367] [<ffffffc000a82d1c>] dump_stack+0x74/0x94
[ 111.367414] [<ffffffc000a81824>] panic+0xec/0x238
[ 111.372116] [<ffffffc000981648>] __inet_twsk_kill+0xd0/0xf8
[ 111.377684] [<ffffffc0009817b0>] inet_twdr_do_twkill_work+0x64/0xd0
[ 111.383946] [<ffffffc000981a5c>] inet_twdr_hangman+0x2c/0xa4
[ 111.389602] [<ffffffc000271cf0>] call_timer_fn+0xac/0x160
[ 111.394995] [<ffffffc00027250c>] run_timer_softirq+0x23c/0x274
[ 111.400824] [<ffffffc000220a68>] __do_softirq+0x1a4/0x330
[ 111.406218] [<ffffffc000220e94>] irq_exit+0x70/0xd0
[ 111.411093] [<ffffffc000264e00>] __handle_domain_irq+0x84/0xa8
[ 111.416922] [<ffffffc0002003ec>] gic_handle_irq+0x4c/0x80
b/22476945
Originally reviewed at:
https://chromium-review.googlesource.com/#/c/297414/
Change-Id: I51fa94a9d92a84a0bd3b58466d711e46a6892a79
Signed-off-by: Dmitry Torokhov <dtor@google.com>
[jstultz: Cherry-picked and added missing local var definition]
Signed-off-by: John Stultz <john.stultz@linaro.org>
[AmitP: Refactored the original changes and updated the commit message
based on following upstream commit changes,
8db4c5be88f6 ("netfilter: move socket lookup infrastructure to nf_socket_ipv{4,6}.c")]
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Removing obsolete xt_socket_put_sk() and using sock_gen_put() instead.
xt_socket_put_sk() was reintroduced for xt_qtaguid in one of the patches,
but it turned out sock_gen_put() supersedes xt_socket_put_sk(). So we
don't need xt_socket_put_sk() any more.
This patch is based on commit 1a8bf6eeef9f (netfilter: xt_socket: use sock_gen_put())
Change-Id: I976d5f7f7eded0f3cc91b596acfeb35e4c2057e5
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
(cherry picked from commit 551780fc28cb7480dbc4f585ef80ca02c2922ec1)
Signed-off-by: John Stultz <john.stultz@linaro.org>
It prevents a kernel panic when accessing sk->sk_socket fields due to NULLing sk->sk_socket when sock_orphan is called through
sk_common_release.
Change-Id: I4aa46b4e2d8600e4d4ef8dcdd363aa4e6e5f8433
Signed-off-by: Mohamad Ayyash <mkayyash@google.com>
(cherry picked from commit cdea0ebcb8bcfe57688f6cb692b49e550ebd9796)
Signed-off-by: John Stultz <john.stultz@linaro.org>
The existing test to check if current uid/gid is within
valid range is broken due to missing parenthesis.
Change-Id: I889ebbd0e2ea6a9426cb1509a2975e7107666407
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Fix up build kuid/kguid build issues in netfilter code.
Also re-add the xt_socket_get/put_sk interfaces needed by xt_qtaguid.
Change-Id: I7027fb840e109785bddffe8ea717b8d018b26d82
Signed-off-by: John Stultz <john.stultz@linaro.org>
Currently, IPv6 router discovery always puts routes into
RT6_TABLE_MAIN. This causes problems for connection managers
that want to support multiple simultaneous network connections
and want control over which one is used by default (e.g., wifi
and wired).
To work around this connection managers typically take the routes
they prefer and copy them to static routes with low metrics in
the main table. This puts the burden on the connection manager
to watch netlink to see if the routes have changed, delete the
routes when their lifetime expires, etc.
Instead, this patch adds a per-interface sysctl to have the
kernel put autoconf routes into different tables. This allows
each interface to have its own autoconf table, and choosing the
default interface (or using different interfaces at the same
time for different types of traffic) can be done using
appropriate ip rules.
The sysctl behaves as follows:
- = 0: default. Put routes into RT6_TABLE_MAIN as before.
- > 0: manual. Put routes into the specified table.
- < 0: automatic. Add the absolute value of the sysctl to the
device's ifindex, and use that table.
The automatic mode is most useful in conjunction with
net.ipv6.conf.default.accept_ra_rt_table. A connection manager
or distribution could set it to, say, -100 on boot, and
thereafter just use IP rules.
Change-Id: I82d16e3737d9cdfa6489e649e247894d0d60cbb1
Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
[AmitP: Refactored original changes to align with
the changes introduced by upstream commit
830218c1add1 ("net: ipv6: Fix processing of RAs in presence of VRF")]
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Create uid from kuid to fix the broken uid field
in the message notifications introduced in
Change-Id: I18fc73eada512e370d7ab24fc9f890845037b729,
Otherwise we run into following build error:
---------------
CC net/netfilter/xt_IDLETIMER.o
net/netfilter/xt_IDLETIMER.c: In function ‘reset_timer’:
net/netfilter/xt_IDLETIMER.c:360:16: error: incompatible types when assigning to type ‘uid_t’ from type ‘kuid_t’
make[2]: *** [net/netfilter/xt_IDLETIMER.o] Error 1
---------------
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
(cherry picked from commit 706060ba3e1dee9ec3c4a4a1480d663b6cd71cad)
Change-Id: Ifd66df45a58d1a5a60c3816c373ee3008292eee8
Message notifications contains an additional uid field. This field
represents the uid that was responsible for waking the radio. And hence
it is present only in notifications stating that the radio is now
active.
Change-Id: I18fc73eada512e370d7ab24fc9f890845037b729
Signed-off-by: Ruchi Kandoi <kandoiruchi@google.com>
Bug: 20264396
The return type of atomic64_read() varies depending on arch. The
arm64 version is being changed from long long to long in the mainline
for v3.16, causing a seq_printf type mismatch (%llu) in
guid_ctrl_proc_show().
This commit fixes the type mismatch by casting atomic64_read() to u64.
Change-Id: Iae0a6bd4314f5686a9f4fecbe6203e94ec0870de
Signed-off-by: Sherman Yin <shermanyin@gmail.com>
Message notifications contains an additional timestamp field in nano seconds.
The expiry time for the timers are modified during suspend/resume.
If timer was supposed to expire while the system is suspended then a
notification is sent when it resumes with the timestamp of the scheduled expiry.
Removes the race condition for multiple work scheduled.
Bug: 13247811
Change-Id: I752c5b00225fe7085482819f975cc0eb5af89bff
Signed-off-by: Ruchi Kandoi <kandoiruchi@google.com>
We need the change below because of mainline commit 351638e7de (net: pass
info struct via netdevice notifier). Otherwise we panic.
Change-Id: I7daf7513a733933fdcbaeebea7f8191f8b6a0432
Signed-off-by: John Stultz <john.stultz@linaro.org>
When calling:
ipv6_find_hdr(skb, &thoff, -1, NULL)
on a fragmented packet, thoff would be left with a random
value causing callers to read random memory offsets with:
skb_header_pointer(skb, thoff, ...)
Now we force ipv6_find_hdr() to return a failure in this case.
Calling:
ipv6_find_hdr(skb, &thoff, -1, &fragoff)
will set fragoff as expected, and not return a failure.
Change-Id: Ib474e8a4267dd2b300feca325811330329684a88
Signed-off-by: JP Abgrall <jpa@google.com>
Since (41063e9 ipv4: Early TCP socket demux), skb's can have an sk which
is not a struct sock but the smaller struct inet_timewait_sock without an
sk->sk_socket. Now we bypass sk_state == TCP_TIME_WAIT
Signed-off-by: JP Abgrall <jpa@google.com>
- Stop using obsolete create_proc_entry api.
- Use proc_set_user instead of directly accessing the private structure.
Signed-off-by: Arve Hjønnevåg <arve@android.com>
Some of the printks are in the packet handling path.
We now ratelimit the very unlikely errors to avoid
kmsg spamming.
Signed-off-by: JP Abgrall <jpa@google.com>
In the past it would always ignore interfaces with loopback addresses.
Now we just treat them like any other.
This also helps with writing tests that check for the presence
of the qtaguid module.
Signed-off-by: JP Abgrall <jpa@google.com>
In the past the iface_stat_fmt would only show global bytes/packets
for the skb-based numbers.
For stall detection in userspace, distinguishing tcp vs other protocols
makes it easier.
Now we report
ifname total_skb_rx_bytes total_skb_rx_packets total_skb_tx_bytes
total_skb_tx_packets {rx,tx}_{tcp,udp,ohter}_{bytes,packets}
Bug: 6818637
Signed-off-by: JP Abgrall <jpa@google.com>
qtaguid limits what can be done with /ctrl and /stats based on group
membership.
This changes removes AID_NET_BW_STATS and AID_NET_BW_ACCT, and picks
up the groups from the gid of the matching proc entry files.
Signed-off-by: JP Abgrall <jpa@google.com>
Change-Id: I42e477adde78a12ed5eb58fbc0b277cdaadb6f94
If create_if_tag_stat fails to allocate memory (GFP_ATOMIC) the
following will happen:
qtaguid: iface_stat: tag stat alloc failed
...
kernel BUG at xt_qtaguid.c:1482!
Signed-off-by: Pontus Fuchs <pontus.fuchs@gmail.com>
qtudev_open() could return with a uid_tag_data_tree_lock held
when an kzalloc(..., GFP_ATOMIC) would fail.
Very unlikely to get triggered AND survive the mayhem of running out of mem.
Signed-off-by: JP Abgrall <jpa@google.com>
In the past, a process could only see its own stats (uid-based summary,
and details).
Now we allow any process to see other UIDs uid-based stats, but still
hide the detailed stats.
Change-Id: I7666961ed244ac1d9359c339b048799e5db9facc
Signed-off-by: JP Abgrall <jpa@google.com>
qtaguid tracks the device stats by monitoring when it goes up and down,
then it gets the dev_stats().
But devs don't correctly report stats (either they don't count headers
symmetrically between rx/tx, or they count internal control messages).
Now qtaguid counts the rx/tx bytes/packets during raw:prerouting and
mangle:postrouting (nat is not available in ipv6).
The results are in
/proc/net/xt_qtaguid/iface_stat_fmt
which outputs a format line (bash expansion):
ifname total_skb_{rx,tx}_{bytes,packets}
Added event counters for pre/post handling.
Added extra ctrl_*() pid/uid debugging.
Change-Id: Id84345d544ad1dd5f63e3842cab229e71d339297
Signed-off-by: JP Abgrall <jpa@google.com>
Send notifications when the label becomes active after an idle period.
Send netlink message notifications in addition to sysfs notifications.
Using a uevent with
subsystem=xt_idletimer
INTERFACE=...
STATE={active,inactive}
This is backport from common android-3.0
commit: beb914e987cbbd368988d2b94a6661cb907c4d5a
with uevent support instead of a new netlink message type.
Change-Id: I31677ef00c94b5f82c8457e5bf9e5e584c23c523
Signed-off-by: Ashish Sharma <ashishsharma@google.com>
Signed-off-by: JP Abgrall <jpa@google.com>
When updating the stats for a given uid it would incorrectly assume
IPV4 and pick up the wrong protocol when IPV6.
Change-Id: Iea4a635012b4123bf7aa93809011b7b2040bb3d5
Signed-off-by: JP Abgrall <jpa@google.com>
There was a case that might have seemed like new_tag_stat was not
initialized and actually used.
Added comment explaining why it was impossible, and a BUG()
in case the logic gets changed.
Change-Id: I1eddd1b6f754c08a3bf89f7e9427e5dce1dfb081
Signed-off-by: JP Abgrall <jpa@google.com>
The xt_quota2 came from
http://sourceforge.net/projects/xtables-addons/develop
It needed tweaking for it to compile within the kernel tree.
Fixed kmalloc() and create_proc_entry() invocations within
a non-interruptible context.
Removed useless copying of current quota back to the iptable's
struct matchinfo:
- those are per CPU: they will change randomly based on which
cpu gets to update the value.
- they prevent matching a rule: e.g.
-A chain -m quota2 --name q1 --quota 123
can't be followed by
-D chain -m quota2 --name q1 --quota 123
as the 123 will be compared to the struct matchinfo's quota member.
Use the NETLINK NETLINK_NFLOG family to log a single message
when the quota limit is reached.
It uses the same packet type as ipt_ULOG, but
- never copies skb data,
- uses 112 as the event number (ULOG's +1)
It doesn't log if the module param "event_num" is 0.
Change-Id: I021d3b743db3b22158cc49acb5c94d905b501492
Signed-off-by: JP Abgrall <jpa@google.com>
The original xt_quota in the kernel is plain broken:
- counts quota at a per CPU level
(was written back when ubiquitous SMP was just a dream)
- provides no way to count across IPV4/IPV6.
This patch is the original unaltered code from:
http://sourceforge.net/projects/xtables-addons
at commit e84391ce665cef046967f796dd91026851d6bbf3
Change-Id: I19d49858840effee9ecf6cff03c23b45a97efdeb
Signed-off-by: JP Abgrall <jpa@google.com>
This module allows tracking stats at the socket level for given UIDs.
It replaces xt_owner.
If the --uid-owner is not specified, it will just count stats based on
who the skb belongs to. This will even happen on incoming skbs as it
looks into the skb via xt_socket magic to see who owns it.
If an skb is lost, it will be assigned to uid=0.
To control what sockets of what UIDs are tagged by what, one uses:
echo t $sock_fd $accounting_tag $the_billed_uid \
> /proc/net/xt_qtaguid/ctrl
So whenever an skb belongs to a sock_fd, it will be accounted against
$the_billed_uid
and matching stats will show up under the uid with the given
$accounting_tag.
Because the number of allocations for the stats structs is not that big:
~500 apps * 32 per app
we'll just do it atomic. This avoids walking lists many times, and
the fancy worker thread handling. Slabs will grow when needed later.
It use netdevice and inetaddr notifications instead of hooks in the core dev
code to track when a device comes and goes. This removes the need for
exposed iface_stat.h.
Put procfs dirs in /proc/net/xt_qtaguid/
ctrl
stats
iface_stat/<iface>/...
The uid stats are obtainable in ./stats.
Change-Id: I01af4fd91c8de651668d3decb76d9bdc1e343919
Signed-off-by: JP Abgrall <jpa@google.com>
Add a family of knobs to /sys/kernel/ipv4 for controlling the TCP window size:
tcp_wmem_min
tcp_wmem_def
tcp_wmem_max
tcp_rmem_min
tcp_rmem_def
tcp_rmem_max
This six values mirror the sysctl knobs in /proc/sys/net/ipv4/tcp_wmem and
/proc/sys/net/ipv4/tcp_rmem.
Sysfs, unlike sysctl, allows us to set and manage the files' permissions and
owners.
Signed-off-by: Robert Love <rlove@google.com>