* Re: [RFC PATCH] poll(): add poll_wait_set_exclusive()
From: Steven Rostedt @ 2010-10-07 20:44 UTC (permalink / raw)
To: Mathieu Desnoyers
Cc: Linus Torvalds, LKML, Andrew Morton, Peter Zijlstra, Ingo Molnar,
Frederic Weisbecker, Thomas Gleixner, Christoph Hellwig, Li Zefan,
Lai Jiangshan, Johannes Berg, Masami Hiramatsu,
Arnaldo Carvalho de Melo, Tom Zanussi, KOSAKI Motohiro,
Andi Kleen, Paul E. McKenney
In-Reply-To: <20101007180737.GA4300@Krystal>
On Thu, 2010-10-07 at 14:07 -0400, Mathieu Desnoyers wrote:
> * Steven Rostedt (rostedt@goodmis.org) wrote:
> > I never mention affinity. As with trace-cmd, it assigns a process per
> > CPU, but those processes can be on any CPU that the scheduler chooses. I
> > could probably do it with a single process reading all the CPU fds too.
> > I might add that as an option.
>
> Your scheme works fine because you have only one stream (and thus one fd) per
> cpu. How would you map that with many streams per cpu ?
>
> Also, you might want to consider using threads rather than processes, to save
> the unnecessary VM swaps.
I thought about threads and could go back to them. I'd have to benchmark
to see the performance hit.
>
> >
> > >
> > > > Or do you have an fd per event per CPU, in which case the threads should just
> > > > poll off of their own fds.
> > >
> > > I have one fd per per-cpu buffer, but there can be many per-cpu buffers, each
> > > transporting a group of events. Therefore, I don't want to associate one thread
> > > per event group, because this would be a resource waste. Typically, only a few
> > > per-cpu buffers will be very active, and others will be very quiet.
> >
> > Lets not talk about threads, what about fds? I'm wondering why you have
> > many threads on the same fd?
>
> That's because I have fewer threads than file descriptors. So I can choose to
> either:
>
> 1) somehow assign each thread to many fds statically or
> 2) make each thread wait for data on all fds
>
> Option (2) adapts much better to workloads where a lots of data would come from
> many file descriptors from a single CPU: all threads can collaboratively work to
> extract the data.
OK, this is what I wanted to know. Now as Linus suggested, go and ask
other application developers (web server developers?) if this is
something that could be useful for them? If you get positive feedback,
have them Cc LKML and we can go from there.
Or, if you see that this type of programming is being done in Apache,
and if you can demonstrate that adding this features helps Apache (or
some other popular program), that would also be of benefit.
-- Steve
^ permalink raw reply
* Re: [tip:core/memblock] x86, memblock: Fix crashkernel allocation
From: H. Peter Anvin @ 2010-10-07 20:44 UTC (permalink / raw)
To: Vivek Goyal
Cc: caiqian@redhat.com, linux-tip-commits@vger.kernel.org,
Kexec Mailing List, linux-kernel@vger.kernel.org,
mingo@redhat.com, tglx@linutronix.de, yinghai@kernel.org
In-Reply-To: <20101007192129.GC2581@redhat.com>
On 10/07/2010 12:21 PM, Vivek Goyal wrote:
>>
>> It would be easy enough to either deprecate or make it an alias for
>> crashkernel=...<896M, which is basically what Yinghai's patch does.
>
> Agreed.
>
> So Yinghai's patch is fine. I need to write a patch for introducing
> crashkernel=X<Y syntax to make the behavior explicit. Will do...
>
Sounds like a plan. Thanks!
-hpa
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply
* Re: [tip:core/memblock] x86, memblock: Fix crashkernel allocation
From: H. Peter Anvin @ 2010-10-07 20:44 UTC (permalink / raw)
To: Vivek Goyal
Cc: mingo@redhat.com, linux-kernel@vger.kernel.org,
yinghai@kernel.org, caiqian@redhat.com, tglx@linutronix.de,
linux-tip-commits@vger.kernel.org, Kexec Mailing List
In-Reply-To: <20101007192129.GC2581@redhat.com>
On 10/07/2010 12:21 PM, Vivek Goyal wrote:
>>
>> It would be easy enough to either deprecate or make it an alias for
>> crashkernel=...<896M, which is basically what Yinghai's patch does.
>
> Agreed.
>
> So Yinghai's patch is fine. I need to write a patch for introducing
> crashkernel=X<Y syntax to make the behavior explicit. Will do...
>
Sounds like a plan. Thanks!
-hpa
^ permalink raw reply
* Attention
From: Liu Tai @ 2010-10-07 20:45 UTC (permalink / raw)
My Names are Mr Liu Tai Ling, I have a business bequest for you to handle with me, kindly indicate your interest along with your names, contact address, age, occupation and telephone number for further details. email: liutai.ling@yahoo.com.hk
^ permalink raw reply
* Re: OT: compilation
From: Grzesiek Sójka @ 2010-10-07 20:46 UTC (permalink / raw)
To: Pekka Paalanen; +Cc: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
In-Reply-To: <20101007233420.1f763477-cxYvVS3buNOdIgDiPM52R8c4bpwCjbIv@public.gmane.org>
On 10/07/10 22:34, Pekka Paalanen wrote:
> Yes, it is CONFIG_LOCALVERSION_AUTO as far as I recall, disable that.
Where is it?? Which file??
^ permalink raw reply
* RE: [PATCH 1/2] drivers:staging:ti-st: move TI_ST from staging
From: Savoy, Pavan @ 2010-10-07 20:46 UTC (permalink / raw)
To: Alan Cox
Cc: Jiri Slaby, gregkh@suse.de, linux-kernel@vger.kernel.org,
devel@driverdev.osuosl.org, linux-bluetooth@vger.kernel.org
In-Reply-To: <20101007215943.45365f45@lxorguk.ukuu.org.uk>
> -----Original Message-----
> From: Alan Cox [mailto:alan@lxorguk.ukuu.org.uk]
> Sent: Thursday, October 07, 2010 4:00 PM
> To: Savoy, Pavan
> Cc: Jiri Slaby; gregkh@suse.de; linux-kernel@vger.kernel.org;
> devel@driverdev.osuosl.org; linux-bluetooth@vger.kernel.org
> Subject: Re: [PATCH 1/2] drivers:staging:ti-st: move TI_ST from staging
>
> > But, I want to attach my data not when ldsic is opened, but when ldisc is
> registered.
> > I want to begin accessing the data when ldisc is opened.
>
> How can you attach per tty data when the ldisc is registered - the
> relevant tty driver might not even have been loaded at that point. The
> user may not even have been to the shop and bought it even !
>
> What sort of data is this ?
Data related to requesting the user-space to open/install the ldisc.
Imagine a UEVENT structure or PID of the user-space process to which I need
to send a signal .. I currently use rfkill.
> > to be like a bunch of helpers (1 for FM, 1 for GPS, 1 for NFC, 1 for power-
> management), also the problem of who owns the /dev/tty begins to occur,
> Bluetooth has a utility called hciattach, I don't want my FM radio software to
> run hciattach when /dev/radio0 is opened and communicated via FM.
>
> I would have assumed the hotplug script would have run your own attach
> and daemon and the FM radio etc would talk to the ldisc via other kernel
> interfaces it presented.
>
> So whenever the hardware is detected it would load the hardware driver
> The hardware driver would create a tty instance for each physical port
> The hotplug user space would run 'ti-st-attach' as a helper which would
> load the ldisc and set up the bluetooth as well as providing exported
> methods for FM radio etc.
Yes, pretty similar to what I am doing now. I have this daemon which waits
for events from my ldisc driver, and on receiving the notification it
opens the uart, ioctl's the TIOCSETD and allows the tty to be accessed over
the ldisc.
> > In any case, the ti-st/ seems better now by look of things, I certainly
> welcome suggestions to improve it.
> > Also, is there any plan to re-write whole of TTY like a the i2C or the SPI
> bus structure?
> >
> > Here I can imagine, all TTY line disciplines being sort of protocol/client
> drivers, the TTY sub-system in itself would be like the algos driver and then
> > The uart drivers (like 8250.c) can be the adapter drivers.. What say?
>
> They already are, with the one oddity being that something needs to have
> it opened from user space and to attach the ldisc. Thats fixable but hard
> to fix and I'm not aware of any plan to do so - mostly because nobody
> needs it so far.
Yes, that oddity was the reason this notification had to be done.
I could as well have opened it up on boot and attached the ldisc, but I chose
to use it whenever other drivers wanted to - as in when hci0 is UP, or /dev/radio0 is opened.
> Alan
^ permalink raw reply
* Re: [Qemu-devel] [PATCH] ceph/rbd block driver for qemu-kvm (v4)
From: Yehuda Sadeh Weinraub @ 2010-10-07 20:47 UTC (permalink / raw)
To: Anthony Liguori
Cc: Christian Brunner, malc, kvm, qemu-devel, Kevin Wolf, ceph-devel
In-Reply-To: <4CAE24C5.8030007@codemonkey.ws>
On Thu, Oct 7, 2010 at 12:51 PM, Anthony Liguori <anthony@codemonkey.ws> wrote:
> On 10/07/2010 01:41 PM, Yehuda Sadeh Weinraub wrote:
>>
>> On Thu, Oct 7, 2010 at 11:38 AM, Anthony Liguori<anthony@codemonkey.ws>
>> wrote:
>>
>>>
>>> On 10/07/2010 01:08 PM, Yehuda Sadeh Weinraub wrote:
>>>
>>>> On Thu, Oct 7, 2010 at 7:12 AM, Anthony Liguori<anthony@codemonkey.ws>
>>>
...
>>> There's no fd at all? How do you get notifications about an
>>> asynchronous
>>> event completion?
>>>
>>> Regards,
>>>
>>> Anthony Liguori
>>>
>>>
>>
>> (resending to list, sorry)
>>
>> The fd is hidden deep under in librados. We get callback notifications
>> for events completion.
>>
>
> How is that possible? Are the callbacks delivered in the context of a
> different thread? If so, don't you need locking?
Not sure I'm completely following you. The callbacks are delivered in
the context of a different thread, but won't run concurrently. Do you
see any specific concurrency issue? We can add some mutex protection
around at the aio callback, so that if librados turns multithreaded at
this point we're covered.
Thanks,
Yehuda
--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [Qemu-devel] [PATCH] ceph/rbd block driver for qemu-kvm (v4)
From: Yehuda Sadeh Weinraub @ 2010-10-07 20:47 UTC (permalink / raw)
To: Anthony Liguori
Cc: Kevin Wolf, kvm, qemu-devel, ceph-devel, Christian Brunner
In-Reply-To: <4CAE24C5.8030007@codemonkey.ws>
On Thu, Oct 7, 2010 at 12:51 PM, Anthony Liguori <anthony@codemonkey.ws> wrote:
> On 10/07/2010 01:41 PM, Yehuda Sadeh Weinraub wrote:
>>
>> On Thu, Oct 7, 2010 at 11:38 AM, Anthony Liguori<anthony@codemonkey.ws>
>> wrote:
>>
>>>
>>> On 10/07/2010 01:08 PM, Yehuda Sadeh Weinraub wrote:
>>>
>>>> On Thu, Oct 7, 2010 at 7:12 AM, Anthony Liguori<anthony@codemonkey.ws>
>>>
...
>>> There's no fd at all? How do you get notifications about an
>>> asynchronous
>>> event completion?
>>>
>>> Regards,
>>>
>>> Anthony Liguori
>>>
>>>
>>
>> (resending to list, sorry)
>>
>> The fd is hidden deep under in librados. We get callback notifications
>> for events completion.
>>
>
> How is that possible? Are the callbacks delivered in the context of a
> different thread? If so, don't you need locking?
Not sure I'm completely following you. The callbacks are delivered in
the context of a different thread, but won't run concurrently. Do you
see any specific concurrency issue? We can add some mutex protection
around at the aio callback, so that if librados turns multithreaded at
this point we're covered.
Thanks,
Yehuda
^ permalink raw reply
* Re: Questions about CRUSH
From: Sage Weil @ 2010-10-07 20:50 UTC (permalink / raw)
To: Wido den Hollander; +Cc: ceph-devel
In-Reply-To: <1286482123.2633.17.camel@wido-laptop.pcextreme.nl>
Hi Wido!
On Thu, 7 Oct 2010, Wido den Hollander wrote:
> Hi,
>
> I'm working on a crushmap where I have my hosts spread out over 3 racks
> (leafs).
>
> I have 9 physical machines, each with one OSD, spread out over three
> racks.
>
> The replication level I intend to use is 3, my goal with this crushmap
> is to prevent two replicas being stored in the same rack.
>
> Now, this map seems fine to me, but what if one of the racks fails and
> the cluster starts to fix itself, then I would get two replicas in the
> same rack, wouldn't I?
Right.
> Is it better to have: leafs at root = (max replication level + 1) ?
>
> So, if I have my replication level set to 3, I should have 4 racks with
> each 3 OSD's, then the cluster could restore from a complete rack
> failure, without compromising my data safety.
>
> When a complete leaf (rack) fails, the other leafs should be able to
> store all the data, so if my replication level is set to 3, I should
> always have at least 1/3 of free space, otherwise a full recovery won't
> be possible, correct? (OSD's run out of disk space).
>
> Am I missing something here or is this the right approach?
Yeah, I think this is the right approach.
> And I'm not completely sure about:
>
> rule placein3racks {
rule placeinNracks {
> ruleset 0
> type replicated
> min_size 2
> max_size 2
min_size 2
max_size 10
> step take root
> step chooseleaf firstn 0 type rack
> step emit
> }
>
> Is that correct? Here I say that the first step should be to choose a
> rack where the replica should be saved. Should I also specify to choose
> a host afterwards?
The rule generalizes to N replicas, where N can be 2..10 (that's what the
min/max size fields are for). And the chooseleaf line is correct. That
chooses N leaves/devices that are nested beneath N distinct racks. Which
is what you want!
You could also do
step take root
step choose firstn 0 type rack
step choose firstn 1 type device
step emit
That would choose N racks, and then for each rack, choose a nested device.
The problem is when one of the racks it chooses has no (or few) online
devices beneath it, we fail to find a usable device, and the result set
will have <N devices. Chooseleaf doesn't have that problem.
sage
^ permalink raw reply
* Re: [Xenomai-core] Overcoming the "foreign" stack
From: Philippe Gerum @ 2010-10-07 20:48 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Xenomai core
In-Reply-To: <4CAE04B1.9070503@domain.hid>
On Thu, 2010-10-07 at 19:34 +0200, Jan Kiszka wrote:
> Am 07.10.2010 19:08, Philippe Gerum wrote:
> > On Wed, 2010-10-06 at 11:20 +0200, Jan Kiszka wrote:
> >> Am 05.10.2010 16:21, Gilles Chanteperdrix wrote:
> >>> Jan Kiszka wrote:
> >>>> Am 05.10.2010 15:50, Gilles Chanteperdrix wrote:
> >>>>> Jan Kiszka wrote:
> >>>>>> Am 05.10.2010 15:42, Gilles Chanteperdrix wrote:
> >>>>>>> Jan Kiszka wrote:
> >>>>>>>> Am 05.10.2010 15:15, Gilles Chanteperdrix wrote:
> >>>>>>>>> Jan Kiszka wrote:
> >>>>>>>>>> Hi,
> >>>>>>>>>>
> >>>>>>>>>> quite a few limitations and complications of using Linux services over
> >>>>>>>>>> non-Linux domains relate to potentially invalid "current" and
> >>>>>>>>>> "thread_info". The non-Linux domain could maintain their own kernel
> >>>>>>>>>> stacks while Linux tend to derive current and thread_info from the stack
> >>>>>>>>>> pointer. This is not an issue anymore on x86-64 (both states are stored
> >>>>>>>>>> in per-cpu variables) but other archs (e.g. x86-32 or ARM) still use the
> >>>>>>>>>> stack and may continue to do so.
> >>>>>>>>>>
> >>>>>>>>>> I just looked into this thing again as I'm evaluating ways to exploit
> >>>>>>>>>> the kernel's tracing framework also under Xenomai. Unfortunately, it
> >>>>>>>>>> does a lot of fiddling with preempt_count and need_resched, so patching
> >>>>>>>>>> it for Xenomai use would become a maintenance nightmare.
> >>>>>>>>>>
> >>>>>>>>>> An alternative, also for other use cases like kgdb and probably perf, is
> >>>>>>>>>> to get rid of our dependency on home-grown stacks. I think we are on
> >>>>>>>>>> that way already as in-kernel skins have been deprecated. The only
> >>>>>>>>>> remaining user after them will be RTDM driver tasks. But I think those
> >>>>>>>>>> could simply become in-kernel shadows of kthreads which would bind their
> >>>>>>>>>> stacks to what Linux provides. Moreover, Xenomai could start updating
> >>>>>>>>>> "current" and "thread_info" on context switches (unless this already
> >>>>>>>>>> happens implicitly). That would give us proper contexts for system-level
> >>>>>>>>>> tracing and profiling.
> >>>>>>>>>>
> >>>>>>>>>> My key question is currently if and how much of this could be realized
> >>>>>>>>>> in 2.6. Could we drop in-kernel skins in that version? If not, what
> >>>>>>>>>> about disabling them by default, converting RTDM tasks to a
> >>>>>>>>>> kthread-based approach, and enabling tracing etc. only in that case?
> >>>>>>>>>> However, this might be a bit fragile unless we can establish
> >>>>>>>>>> compile-time or run-time requirements negotiation between Adeos and its
> >>>>>>>>>> users (Xenomai) about the stack model.
> >>>>>>>>> A stupid question: why not make things the other way around: patch the
> >>>>>>>>> current and current_thread_info functions to be made I-pipe aware and
> >>>>>>>>> use an "ipipe_current" pointer to the current thread task_struct. Of
> >>>>>>>>> course, there are places where the current or current_thread_info macros
> >>>>>>>>> are implemented in assembly, so it may be not simple as it sounds, but
> >>>>>>>>> it would allow to keep 128 Kb stacks if we want. This also means that we
> >>>>>>>>> would have to put a task_struct at the bottom of every Xenomai task.
> >>>>>>>> First of all, overhead vs. maintenance. Either every access to
> >>>>>>>> preempt_count() would require a check for the current domain and its
> >>>>>>>> foreign stack flag, or I would have to patch dozens (if that is enough)
> >>>>>>>> of code sites in the tracer framework.
> >>>>>>> No. I mean we would dereference a pointer named ipipe_current. That is
> >>>>>>> all, no other check. This pointer would be maintained elsewhere. And we
> >>>>>>> modify the "current" macro, like:
> >>>>>>>
> >>>>>>> #ifdef CONFIG_IPIPE
> >>>>>>> extern struct task_struct *ipipe_current;
> >>>>>>> #define current ipipe_current
> >>>>>>> #endif
> >>>>>>>
> >>>>>>> Any calll site gets modified automatically. Or current_thread_info, if
> >>>>>>> it is current_thread_info which is obtained using the stack pointer mask
> >>>>>>> trick.
> >>>>>> The stack pointer mask trick only works with fixed-sized stacks, not a
> >>>>>> guaranteed property of in-kernel Xenomai threads.
> >>>>> Precisely the reason why I propose to replace it with a global variable
> >>>>> reference, or a per-cpu variable for SMP systems.
> >>>>
> >>>> Then why is Linux not using this in favor of the stack pointer approach
> >>>> on, say, ARM?
> >>>>
> >>>> For sure, we can patch all Adeos-supported archs away from stack-based
> >>>> to per-cpu current & thread_info, but I don't feel comfortable with this
> >>>> in some way invasive approach as well. Well, maybe it's just my personal
> >>>> misperception.
> >>>
> >>> It is as much invasive as modifying local_irq_save/local_irq_restore.
> >>> The real question about the global pointer approach, is, if it so much
> >>> less efficient, how does Xenomai, which uses this scheme, manage to have
> >>> good performances on ARM?
> >>
> >> Xenomai has no heavily-used preempt_disable/enable that is built on top
> >> of thread_info. But I also have no numbers on this.
> >>
> >> I looked closer at the kernel dependencies on a fixed stack size.
> >> Besides current and thread_info, further features that make use of this
> >> are stack unwinding (boundary checks) and overflow checking. So while we
> >> can work around the dependency for some tracing requirements, I really
> >> see no point in heading for this long-term. It just creates more subtle
> >> patching needs in Adeos, and it also requires work on Xenomai side. I
> >> really think it's better provide a compatible context to reduce
> >> maintenance efforts.
> >>
> >> So I played a bit with converting RTDM tasks to in-kernel shadows. It
> >> works but needs more fine-tuning. My proposal for 2.6 now looks like this:
> >>
> >> - add mm-less shadow support to the nucleus (changes in
> >> xnarch_switch_to and xnshadow_map)
> >> - convert RTDM tasks to in-kernel shadows
> >> - switch current and thread_info on Xenomai task switches
> >> - make in-kernel skins optional, default off
> >> - let in-kernel skins dependent on disabled tracing
> >
> > I agree with your approach of moving to kernel space shadows, this is
> > the best way to get rid of foreign stacks. Those are a relic of the
> > kernel-only era, this introduces painful constraints, e.g. in low-level
> > thread switching code (i.e. so-called "hybrid" scheduling) and other
> > weirdnesses. This definitely has to go.
> >
> > I'm on a wait and see stance about generalizing the use of the ftrace
> > framework for our needs; like Gilles saw with ARM, I must admit that I
> > did notice a massive overhead on low-end ppc as well when we moved the
> > pipeline tracer over it. I'm aware of the mcount optimizations that
> > should be there when cycles really matter, and that ftrace does branch
> > directly to the trace function when only a single one exists, but this
> > may not be easy to keep after the generalization has taken place.
> > Anyway, I'll wait for more data to make my opinion.
>
> As I said, ftrace is more the a simple mcount-tracer. And it's standard,
> distros start to enable it in their production kernels these days
> (except for the function tracer).
>
> If the overhead of the ftrace's mcount is too high on low-end platforms
> (I personally haven't tried it there yet), it would probably be a good
> idea to develop some optimizations or allow some variant that does not
> suffer that much - but upstream then.
>
> >
> > However, those changes can't be targeted at 2.6. The rationale for
> > issuing 2.6 is really about cleaning up some ABI issues and merging
> > invasive but non-critical infrastructure changes, so that we can
> > maintain the 2.x series for a long time without being stuck by the ABI
> > constraints of 2.5.x. Your proposal is clean material for 3.x though,
> > given that we won't even have to bother with in-kernel skin APIs there.
>
> OK, I see. This will be too late for our next version I'm afraid.
>
> But maybe we can establish some intermediate solutions, at least for
> x86-64 where we do not have that many problems with kernel-stack-based
> information. That would allow to explore the potentials of ftrace and
> tools a bit earlier.
>
We could use your tree to host this provided you rebase on -head, and
feed the forge with that material when it is a ready for prime time.
> >
> > This said, I understand we need a branch to experiment radical changes
> > aimed at 3.x, but xenomai-head is no place for that. I have been
> > tracking -head for some time, doing massive cuts in the code to
> > eliminate most of the obvious legacy we don't want to care about anymore
> > (e.g. 2.4 kernel support, in-kernel skin APIs, and a few others). I will
> > shortly open a new tree on git.xenomai.org called "forge" with that code
> > base, so that we have the proper playground to get wild with our
> > chainsaws in the Xenomai core aimed at 3.x.
>
> Looking forward to seeing this.
>
> I actually ran into one compatibility conflict with my shadow rtdm task
> as well: Someone specified rtdm_task_init as RT-safe, and some strange
> network stack called RTnet indeed made use of this.
Yeah, kids these days...
> Would be easier to
> simply require a driver update for a new RTDM version than establishing
> a compatibility workaround.
>
It would make sense to me as well. There are not that many opportunity
to change some bad rules from a good game, and one of them happens now
with 3.x.
> Jan
>
--
Philippe.
^ permalink raw reply
* Re: [PATCH] serial: DCC(JTAG) serial and console emulation support
From: Mike Frysinger @ 2010-10-07 20:47 UTC (permalink / raw)
To: Daniel Walker
Cc: linux-kernel, Hyok S. Choi, Tony Lindgren, Jeff Ohlstein,
Greg Kroah-Hartman, Ben Dooks, Alan Cox, Kukjin Kim, Feng Tang,
Tobias Klauser, Jason Wessel, Philippe Langlais
In-Reply-To: <1286482013.23836.29.camel@c-dwalke-linux.qualcomm.com>
On Thu, Oct 7, 2010 at 16:06, Daniel Walker wrote:
> On Thu, 2010-10-07 at 16:02 -0400, Mike Frysinger wrote:
>> how is that any different from:
>> ln -s ttyJ0 /dev/ttyS0
>
> It has the same major and minors as ttyS* does. So you don't have to run
> anything on the target.
i dont see how those things are related. the major/minor are
irrelevant, unless you've already hard coded these in some app that
creates device nodes manually (instead of mdev/udev), but even then
that's something that "needs to be run on the target". and both
already have config support to transparently do something like
"symlink ttyS# to XXX" as XXX is created.
-mike
^ permalink raw reply
* Re: [PATCH 0/7] a couple of random cleanups
From: Alex Elder @ 2010-10-07 20:49 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: xfs
In-Reply-To: <20101006184111.634126439@localhost.localdomain>
On Wed, 2010-10-06 at 14:41 -0400, Christoph Hellwig wrote:
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs
The whole series looks fine. I'm taking them in and will
start testing with them.
-Alex
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply
* Re: Can you please define "snapshot" and "subvolume"?
From: David Nicol @ 2010-10-07 20:48 UTC (permalink / raw)
To: Francis Galiegue; +Cc: linux-btrfs
In-Reply-To: <AANLkTimBsVGS=eJvpdf2Sq_Dg76zQRgy=E+3089zQ9D4@mail.gmail.com>
On Thu, Oct 7, 2010 at 6:39 AM, Francis Galiegue <fgaliegue@gmail.com> wrote:
> While I fully understand (and use) the purpose of snapshots, I don't
> quite fathom the use case for subvolumes, apart from btrfs-convert...
> Why has btrfs grown such a feature in the first place? Can someone
> give me a use case for them?
I'm new here; I trust that someone will correct me if wrong:
As I understand it, since snapshotting works on volumes, having
subvolumes allows a smaller thing that you can take a snapshot of. A
use case? One could give each user on a multi-user system their own
subvolume rather than their own directory, under /home/... and then
take snapshots of these home directories to implement regular backups
(1)without duplicating unchanged files and (2) with independence
between the users.
As to why they exist, I understand that they began as an
implementation detail of snapshots, rather than their creation having
been driven by the needs of a particular use case, and one could
legitimately criticize currently offered use cases (such as the one
above) as contrived.
I believe it is fair to consider a new subvolume as equivalent of a
snapshot of an empty file system.
^ permalink raw reply
* Re: [PATCH] dell-laptop: Add hwswitch_only module parameter
From: Mario Limonciello @ 2010-10-07 20:49 UTC (permalink / raw)
To: Matthew Garrett
Cc: Keng-Yu Lin, len.brown, alan-jenkins, platform-driver-x86,
linux-kernel
In-Reply-To: <20101007133529.GA21782@srcf.ucam.org>
Hi Matthew:
On Thu, Oct 7, 2010 at 08:35, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
>
> On Thu, Oct 07, 2010 at 08:30:57AM -0500, Mario Limonciello wrote:
>
> > In this specific scenario that Ken Yu submitted this patch for, the
> > firmware will return the same return codes for the SMI's as a functional
> > machine will. Machines affected by this will fail to recover after rfkill
> > is toggled twice. The symptom will be that the soft block always appears
> > set to the same setting with continued keypresses.
> > During the prototype phase this option is quite useful to help debug the
> > problem it addresses.
>
> Is the kernel able to unblock it under those circumstances?
Manually running rfkill unblock will unblock it in this broken
firmware scenario in question.
--
Mario Limonciello
superm1@gmail.com
^ permalink raw reply
* CLEVO B5120 acpi problems, probably EC-related
From: Oliver Freyd @ 2010-10-07 20:45 UTC (permalink / raw)
To: linux-acpi
Hello,
I'm trying to get this new laptop running with linux (debian testing)
most things are working well, I get acpi events for hotkeys
like volume up/down, or light up/down, but no acpi_events
or even interrupts for the sleep button, the power button,
lid switch and AC power plug.
uname -a
Linux falkenstein 2.6.32-5-amd64 #1 SMP Fri Sep 17 21:50:19 UTC 2010
x86_64 GNU/Linux
dmesg|grep ACPI says:
[ 0.000000] Using ACPI (MADT) for SMP configuration information
[ 0.000000] ACPI: HPET id: 0x8086a701 base: 0xfed00000
[ 0.002994] ACPI: Core revision 20090903
[ 0.497370] ACPI: bus type pci registered
[ 0.512734] ACPI: EC: Look up EC in DSDT
[ 0.518819] ACPI: BIOS _OSI(Linux) query ignored
[ 0.520679] ACPI: EC: GPE storm detected, transactions will use
polling mode
[ 0.540248] ACPI: Interpreter enabled
[ 0.540252] ACPI: (supports S0 S3 S4 S5)
[ 0.540287] ACPI: Using IOAPIC for interrupt routing
[ 0.540597] [Firmware Bug]: ACPI: ACPI brightness control misses _BQC
function
[ 0.575483] [Firmware Bug]: ACPI: ACPI brightness control misses _BQC
function
[ 0.612412] ACPI: EC: GPE = 0x17, I/O: command/status = 0x66, data = 0x62
[ 0.612664] ACPI: No dock devices found.
[ 0.613466] ACPI: PCI Root Bridge [PCI0] (0000:00)
[ 0.628222] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0._PRT]
[ 0.628467] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.P0P2._PRT]
[ 0.628586] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.P0P1._PRT]
[ 0.628785] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.RP01._PRT]
[ 0.628900] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.RP02._PRT]
[ 0.629015] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.RP03._PRT]
[ 0.629129] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.RP04._PRT]
[ 0.639287] ACPI: PCI Root Bridge [CPBG] (0000:ff)
[ 0.639612] ACPI: PCI Interrupt Link [LNKA] (IRQs 1 3 4 5 6 7 10 12
14 15) *11
[ 0.639713] ACPI: PCI Interrupt Link [LNKB] (IRQs 1 3 4 5 6 7 11 12
14 15) *10
[ 0.639812] ACPI: PCI Interrupt Link [LNKC] (IRQs 1 3 4 5 6 7 *10 12
14 15)
[ 0.639911] ACPI: PCI Interrupt Link [LNKD] (IRQs 1 3 4 *5 6 7 11 12
14 15)
[ 0.640009] ACPI: PCI Interrupt Link [LNKE] (IRQs 1 3 4 5 6 7 10 12
14 15) *0, disabled.
[ 0.640114] ACPI: PCI Interrupt Link [LNKF] (IRQs 1 3 4 5 6 7 11 12
14 15) *0, disabled.
[ 0.640215] ACPI: PCI Interrupt Link [LNKG] (IRQs 1 3 4 5 6 *7 10 12
14 15)
[ 0.640314] ACPI: PCI Interrupt Link [LNKH] (IRQs 1 3 4 5 6 7 *11 12
14 15)
[ 0.640454] PCI: Using ACPI for IRQ routing
[ 0.649093] pnp: PnP ACPI init
[ 0.649105] ACPI: bus type pnp registered
[ 0.665529] pnp: PnP ACPI: found 11 devices
[ 0.665530] ACPI: ACPI bus type pnp unregistered
[ 1.083544] ACPI Error (psargs-0359): [\_PR_.CPU0._PPC] Namespace
lookup failure, AE_NOT_FOUND
[ 1.083550] ACPI Error (psparse-0537): Method parse/execution failed
[\_SB_.PCI0.LPCB.EC__.ADJP] (Node ffff880137a40240), AE_NOT_FOUND
[ 1.083581] ACPI Error (psparse-0537): Method parse/execution failed
[\_TZ_.TZ0_._TMP] (Node ffff880137a44de0), AE_NOT_FOUND
[ 3.203371] ACPI: SSDT 00000000bf71a918 003F0 (v01 PmRef Cpu0Ist
00003000 INTL 20060912)
[ 3.203922] ACPI: SSDT 00000000bf718a18 00471 (v01 PmRef Cpu0Cst
00003001 INTL 20060912)
[ 3.218859] ACPI: Power Button [PWRB]
[ 3.218919] ACPI: Sleep Button [SLPB]
[ 3.223950] ACPI: SSDT 00000000bf719a98 00303 (v01 PmRef ApIst
00003000 INTL 20060912)
[ 3.224539] ACPI: SSDT 00000000bf717d98 00119 (v01 PmRef ApCst
00003000 INTL 20060912)
[ 3.293155] ACPI: Lid Switch [LID0]
[ 3.293230] ACPI: WMI: Mapper loaded
[ 3.293237] ACPI: Power Button [PWRF]
[ 3.328155] ACPI: AC Adapter [AC] (on-line)
[ 3.377779] [Firmware Bug]: ACPI(VGA) defines _DOD but not _DOS
[ 3.377905] [Firmware Bug]: ACPI: ACPI brightness control misses _BQC
function
[ 3.517464] acpi device:01: registered as cooling_device4
[ 3.517750] ACPI: Video Device [VGA] (multi-head: yes rom: no post: no)
[ 4.015196] ACPI: Battery Slot [BAT] (battery present)
[ 4.020328] ACPI: I/O resource 0000:00:1f.3 [0x1840-0x185f] conflicts
with ACPI region SMBI [0x1840-0x184f]
[ 4.020388] ACPI: If an ACPI driver is available for this device, you
should use it instead of the native driver
[ 8.689480] input: ACPI Virtual Keyboard Device as
/devices/virtual/input/input11
especially strange I find the "EC GPE storm detected" and the 3
AE_NOT_FOUND errors.
I tried to decompile the DSDT, and was able to compile it back after
fixing some rather trivial errors, but I'm at a loss with the missing
methods.
I also tried a 2.6.36rc1 kernel, compiled from source,
the missing methods in dmesg were gone, but the buttons did not
work either...
lots of fun hacking linux,
Oliver
^ permalink raw reply
* Re: OT: compilation
From: Xavier Chantry @ 2010-10-07 20:50 UTC (permalink / raw)
To: Grzesiek Sójka; +Cc: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
In-Reply-To: <4CAE2A1B.1000105-t9zbU3WrWHI@public.gmane.org>
2010/10/7 Grzesiek Sójka <pld-t9zbU3WrWHI@public.gmane.org>:
> I have two problems with the kernel compilation.
>
> 1. I have a small rootfs. It is too small to put all the modules there
> without gzipping it first. So installing it requires lots of sweating. That
> is why I was wondering if there is a (more/less easy) way to make the "make
> modules_install" command gzip the modules "on the fly".
>
No idea if you can do that but here are some possible alternatives :
1) increase the size of your rootfs
2) remove modules you don't need and change from modules to builtin
for features or drivers that you don't need to unload/reload
3) a quick googling showed me this patch :
http://www.mail-archive.com/linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org/msg271865.html
However it seems to install first then compress so if that's the case,
you will need to adapt it to your need
4) set INSTALL_MOD_PATH to a prefix , compress modules , then move to
/lib/modules/
LOCALVERSION_AUTO is found in :
make menuconfig
General Setup
Automatically append version information to the version string
^ permalink raw reply
* Re: Restricting USB access
From: Greg KH @ 2010-10-07 20:50 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <OFACC41AE7.587D1697-ON852577B5.006C93B7-852577B5.006D0ACC@hc-sc.gc.ca>
On Thu, Oct 07, 2010 at 03:50:55PM -0400, Ryan Lawrie wrote:
>
> Good afternoon,
>
> Just wondering if I could get your assistance with something.
>
> I need to secure the USB ports on my LAN workstations so they are not
> writable by users (other than a certain group that I specify). Is this type
> of restriction possible using udev rules?
USB ports are "writeable" or "readable", it depends on the devices you
plug into them that you could then read or write to.
> I was using PolicyKit before but since we've changed OS (from openSUSE11.0
> to 64-bit openSUSE11.2) that no longer seems to function properly.
> Everybody has access to the USB ports now.
You might want to just restrict the users for the specific devices using
a udev rule, or policykit, if that's still around.
What types of devices are you trying to restrict?
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH] usb: gadget: langwell_udc: Fix error path
From: Greg KH @ 2010-10-07 20:48 UTC (permalink / raw)
To: Rahul Ruikar
Cc: David Brownell, Greg Kroah-Hartman, Joe Perches, linux-usb,
linux-kernel
In-Reply-To: <AANLkTinxOAFuBjUaZVxHAM_n+xcV1qVEgVZ-up9kDRDP@mail.gmail.com>
On Thu, Oct 07, 2010 at 11:49:41PM +0530, Rahul Ruikar wrote:
> Ok no problem.
> I had sent it because yesterday you asked me to send it again.
Yes, but I assumed it would be in a form that I could apply it in :)
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH] dell-laptop: Add hwswitch_only module parameter
From: Matthew Garrett @ 2010-10-07 20:50 UTC (permalink / raw)
To: Mario Limonciello
Cc: Keng-Yu Lin, len.brown, alan-jenkins, platform-driver-x86,
linux-kernel
In-Reply-To: <AANLkTi=kTQpTkCF6-DE+LdNLH_aki9bD9NPF0L2qRr=Q@mail.gmail.com>
On Thu, Oct 07, 2010 at 03:49:05PM -0500, Mario Limonciello wrote:
> Hi Matthew:
> > Is the kernel able to unblock it under those circumstances?
>
> Manually running rfkill unblock will unblock it in this broken
> firmware scenario in question.
So the issue is in the firmware's response to the keystroke? Ok. I'd
rather have a DMI list of the broken machines than a module parameter.
--
Matthew Garrett | mjg59@srcf.ucam.org
^ permalink raw reply
* Re: [PATCH] serial: DCC(JTAG) serial and console emulation support
From: Daniel Walker @ 2010-10-07 20:51 UTC (permalink / raw)
To: Alan Cox
Cc: linux-kernel, Hyok S. Choi, Tony Lindgren, Jeff Ohlstein,
Greg Kroah-Hartman, Ben Dooks, Alan Cox, Kukjin Kim,
Mike Frysinger, Feng Tang, Tobias Klauser, Jason Wessel,
Philippe Langlais
In-Reply-To: <20101007220538.2294a7e4@lxorguk.ukuu.org.uk>
On Thu, 2010-10-07 at 22:05 +0100, Alan Cox wrote:
> On Thu, 07 Oct 2010 13:36:06 -0700
> Daniel Walker <dwalker@codeaurora.org> wrote:
>
> > On Thu, 2010-10-07 at 21:50 +0100, Alan Cox wrote:
> > > > + Say Y here if you want to install DCC driver as a normal serial port
> > > > + /dev/ttyS0 (major 4, minor 64). Otherwise, it appears as /dev/ttyJ0
> > > > + (major 4, minor 128) and can co-exist with other UARTs, such as
> > > > + 8250/16C550 compatibles.
> > > > +
> > >
> > > NAK to both
> >
> > Both what?
>
> Both device allocations. Please use the 204,186 assigned for JTAG DCC.
>
> > I would agree if this wasn't strictly for debugging embedded devices in
> > difficult situations.. After talking to Mike, it's seems like it would
> > be useful to have this as a ttyS* specifically because embedded devices
> > won't always create a ttyJ* for you and ttyS* will likely already exist.
>
> If you are debugging an embedded device you are capable of changing it
> (otherwise you wouldn't debug it). Therefore the fact you might need to
> tweak the tty creation on the device is not a problem. If you can't
> change the device well there is no point debugging it is there !
Your making too many assumptions .. You might be able to modify the
kernel, and not the userspace. So you couldn't tweak the device
creation .. It's much easier in the server world ..
Hyok should really be addressing this .. If he added for some random
useless reason , then for sure we can rip it out .. Otherwise I think it
deserves some more discussion ..
> We've said no over a period of about ten years to a lot of attempts to
> just borrow the ttyS0 range. If we'd said yes it would have been a
> complete mess by now.
>
> So the answer is no.
Nothing can be unilateral, there's always room for exceptions. You
should say something more like "it's possible, but unlikely".
Daniel
--
Sent by a consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply
* Re: Can you please define "snapshot" and "subvolume"?
From: David Nicol @ 2010-10-07 20:52 UTC (permalink / raw)
To: Mike Hommey; +Cc: Jérôme Poulin, Francis Galiegue, linux-btrfs
In-Reply-To: <20101007131823.GB1536@glandium.org>
On Thu, Oct 7, 2010 at 8:18 AM, Mike Hommey <mh@glandium.org> wrote:
> BTW, it would be very useful to be able to turn existing directories
> into subvolumes.
does a (link,unlink) move work across subvolumes?
^ permalink raw reply
* [PATCH v1 1/4] lib: hex2bin converts ascii hexadecimal string to binary
From: Mimi Zohar @ 2010-10-07 20:52 UTC (permalink / raw)
To: linux-kernel
Cc: Mimi Zohar, linux-security-module, keyrings, linux-crypto,
David Howells, James Morris, David Safford, Rajiv Andrade,
Mimi Zohar
In-Reply-To: <1286484734-3119-1-git-send-email-zohar@linux.vnet.ibm.com>
Similar to the kgdb_hex2mem() code, hex2bin converts a string
to binary using the hex_to_bin() library call.
Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
---
include/linux/kernel.h | 1 +
lib/hexdump.c | 16 ++++++++++++++++
2 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 2b0a35e..69ddea8 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -396,6 +396,7 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
}
extern int hex_to_bin(char ch);
+extern void hex2bin(unsigned char *mem, char *buf, int count);
#ifndef pr_fmt
#define pr_fmt(fmt) fmt
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 5d7a480..66f96bb 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -34,6 +34,22 @@ int hex_to_bin(char ch)
EXPORT_SYMBOL(hex_to_bin);
/**
+ * hex2bin - convert an ascii hexadecimal string to its binary representation
+ * @mem: result
+ * @buf: ascii hexadecimal string
+ * @count: result length
+ */
+void hex2bin(unsigned char *mem, char *buf, int count)
+{
+ while (count--) {
+ *mem = hex_to_bin(*buf++) << 4;
+ *mem += hex_to_bin(*buf++);
+ mem++;
+ }
+}
+EXPORT_SYMBOL(hex2bin);
+
+/**
* hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
* @buf: data blob to dump
* @len: number of bytes in the @buf
--
1.7.2.2
^ permalink raw reply related
* [PATCH v1 3/4] keys: add new trusted key-type
From: Mimi Zohar @ 2010-10-07 20:52 UTC (permalink / raw)
To: linux-kernel
Cc: Mimi Zohar, linux-security-module, keyrings, linux-crypto,
David Howells, James Morris, David Safford, Rajiv Andrade,
Mimi Zohar
In-Reply-To: <1286484734-3119-1-git-send-email-zohar@linux.vnet.ibm.com>
Defines a new kernel key-type called 'trusted'. Trusted keys are TPM
generated random numbers, RSA sealed by the TPM, and only unsealed by
the TPM, if boot PCRs and other criteria match. Trusted keys are
created/encrypted/decrypted in the kernel. Userspace ever only
sees/stores encrypted blobs.
Signed-off-by: David Safford <safford@watson.ibm.com>
Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
---
include/keys/trusted-type.h | 33 ++
security/Kconfig | 15 +
security/keys/Makefile | 1 +
security/keys/trusted_defined.c | 997 +++++++++++++++++++++++++++++++++++++++
security/keys/trusted_defined.h | 125 +++++
5 files changed, 1171 insertions(+), 0 deletions(-)
create mode 100644 include/keys/trusted-type.h
create mode 100644 security/keys/trusted_defined.c
create mode 100644 security/keys/trusted_defined.h
diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
new file mode 100644
index 0000000..be7d44e
--- /dev/null
+++ b/include/keys/trusted-type.h
@@ -0,0 +1,33 @@
+/* trusted-type.h: trusted-defined key type
+ *
+ * Copyright (C) 2010 IBM Corporation
+ * Author: David Safford <safford@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ */
+
+#ifndef _KEYS_TRUSTED_TYPE_H
+#define _KEYS_TRUSTED_TYPE_H
+
+#include <linux/key.h>
+#include <linux/rcupdate.h>
+
+#define MAX_KEY_SIZE 128
+#define MAX_BLOB_SIZE 320
+#define MAX_PCRINFO_SIZE 64
+
+struct trusted_key_payload {
+ struct rcu_head rcu; /* RCU destructor */
+ unsigned int key_len;
+ unsigned int blob_len;
+ unsigned int pcrinfo_len;
+ unsigned char key[MAX_KEY_SIZE];
+ unsigned char blob[MAX_BLOB_SIZE];
+ unsigned char pcrinfo[MAX_PCRINFO_SIZE];
+};
+
+extern struct key_type key_type_trusted;
+
+#endif /* _KEYS_TRUSTED_TYPE_H */
diff --git a/security/Kconfig b/security/Kconfig
index bd72ae6..38fdaf6 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -21,6 +21,21 @@ config KEYS
If you are unsure as to whether this is required, answer N.
+config TRUSTED_KEYS
+ tristate "TRUSTED KEYS"
+ depends on KEYS && TCG_TPM
+ select CRYPTO
+ select CRYPTO_HMAC
+ select CRYPTO_SHA1
+ help
+ This option provides support for creating/sealing/unsealing keys
+ in the kernel. Trusted keys are TPM generated random numbers
+ symmetric keys, RSA sealed by the TPM, and only unsealed by the
+ TPM, if boot PCRs and other criteria match. Userspace ever only
+ sees/stores encrypted blobs.
+
+ If you are unsure as to whether this is required, answer N.
+
config KEYS_DEBUG_PROC_KEYS
bool "Enable the /proc/keys file by which keys may be viewed"
depends on KEYS
diff --git a/security/keys/Makefile b/security/keys/Makefile
index 74d5447..fcb1070 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -13,6 +13,7 @@ obj-y := \
request_key_auth.o \
user_defined.o
+obj-$(CONFIG_TRUSTED_KEYS) += trusted_defined.o
obj-$(CONFIG_KEYS_COMPAT) += compat.o
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/security/keys/trusted_defined.c b/security/keys/trusted_defined.c
new file mode 100644
index 0000000..aedad16
--- /dev/null
+++ b/security/keys/trusted_defined.c
@@ -0,0 +1,997 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * David Safford <safford@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ *
+ * File: trusted_defined.c
+ *
+ * Defines a new kernel key-type called 'trusted'. Trusted keys are
+ * TPM generated random numbers, RSA sealed by the TPM, and only unsealed
+ * by the TPM, if boot PCRs and other criteria match. Trusted keys are
+ * created/sealed/unsealed in the kernel. Userspace ever only sees/stores
+ * encrypted blobs.
+ *
+ * Keys are sealed under the SRK, which must have the default
+ * authorization value (20 zeros). This can be set at takeownership
+ * time with the trouser's utility "tpm_takeownership -u -z".
+ *
+ * Usage:
+ * keyctl add trusted name "NEW keylen [hex_pcrinfo]" ring
+ * keyctl add trusted name "LOAD hex_blob" ring
+ * keyctl update key "UPDATE hex_pcrinfo"
+ * keyctl print keyid
+ * keys can be 32 - 128 bytes, blob max is 1024 hex ascii characters
+ * binary pcrinfo max is 512 hex ascii characters
+ */
+
+#include <linux/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/parser.h>
+#include <linux/string.h>
+#include <keys/user-type.h>
+#include <keys/trusted-type.h>
+#include <linux/key-type.h>
+#include <linux/random.h>
+#include <linux/rcupdate.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <linux/tpm.h>
+
+#include "trusted_defined.h"
+
+static char hmac_alg[] = "hmac(sha1)";
+static char hash_alg[] = "sha1";
+
+static int init_sha1_desc(struct hash_desc *desc)
+{
+ int rc;
+
+ desc->tfm = crypto_alloc_hash(hash_alg, 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(desc->tfm)) {
+ rc = PTR_ERR(desc->tfm);
+ return rc;
+ }
+ desc->flags = 0;
+ rc = crypto_hash_init(desc);
+ if (rc)
+ crypto_free_hash(desc->tfm);
+ return rc;
+}
+
+static int init_hmac_desc(struct hash_desc *desc, unsigned char *key,
+ int keylen)
+{
+ int rc;
+
+ desc->tfm = crypto_alloc_hash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(desc->tfm)) {
+ rc = PTR_ERR(desc->tfm);
+ return rc;
+ }
+ desc->flags = 0;
+ crypto_hash_setkey(desc->tfm, key, keylen);
+ rc = crypto_hash_init(desc);
+ if (rc)
+ crypto_free_hash(desc->tfm);
+ return rc;
+}
+
+static int TSS_sha1(unsigned char *data, int datalen, unsigned char *digest)
+{
+ struct hash_desc desc;
+ struct scatterlist sg[1];
+ int rc;
+
+ rc = init_sha1_desc(&desc);
+ if (rc != 0)
+ return rc;
+
+ sg_init_one(sg, data, datalen);
+ crypto_hash_update(&desc, sg, datalen);
+ crypto_hash_final(&desc, digest);
+ crypto_free_hash(desc.tfm);
+ return rc;
+}
+
+static int TSS_rawhmac(unsigned char *digest, unsigned char *key,
+ unsigned int keylen, ...)
+{
+ struct hash_desc desc;
+ struct scatterlist sg[1];
+ unsigned int dlen;
+ unsigned char *data;
+ va_list argp;
+ int error;
+
+ error = init_hmac_desc(&desc, key, keylen);
+ if (error)
+ return error;
+
+ va_start(argp, keylen);
+ for (;;) {
+ dlen = (unsigned int)va_arg(argp, unsigned int);
+ if (dlen == 0)
+ break;
+ data = (unsigned char *)va_arg(argp, unsigned char *);
+ if (data == NULL)
+ return -1;
+ sg_init_one(sg, data, dlen);
+ crypto_hash_update(&desc, sg, dlen);
+ }
+ crypto_hash_final(&desc, digest);
+ crypto_free_hash(desc.tfm);
+
+ va_end(argp);
+ return 0;
+}
+
+/*
+ * calculate authorization info fields to send to TPM
+ */
+static uint32_t TSS_authhmac(unsigned char *digest, unsigned char *key,
+ unsigned int keylen, unsigned char *h1,
+ unsigned char *h2, unsigned char h3, ...)
+{
+ unsigned char paramdigest[TPM_HASH_SIZE];
+ struct hash_desc desc;
+ struct scatterlist sg[1];
+ unsigned int dlen;
+ unsigned char *data;
+ unsigned char c;
+ int rc;
+
+ va_list argp;
+
+ rc = init_sha1_desc(&desc);
+ if (rc != 0)
+ return rc;
+ c = h3;
+ va_start(argp, h3);
+ for (;;) {
+ dlen = (unsigned int)va_arg(argp, unsigned int);
+ if (dlen == 0)
+ break;
+ data = (unsigned char *)va_arg(argp, unsigned char *);
+ sg_init_one(sg, data, dlen);
+ rc = crypto_hash_update(&desc, sg, dlen);
+ }
+ va_end(argp);
+ rc = crypto_hash_final(&desc, paramdigest);
+ crypto_free_hash(desc.tfm);
+ TSS_rawhmac(digest, key, keylen, TPM_HASH_SIZE, paramdigest,
+ TPM_NONCE_SIZE, h1, TPM_NONCE_SIZE, h2, 1, &c, 0, 0);
+ return 0;
+}
+
+/*
+ * verify the AUTH1_COMMAND (Seal) result from TPM
+ */
+static uint32_t TSS_checkhmac1(unsigned char *buffer, uint32_t command,
+ unsigned char *ononce, unsigned char *key,
+ unsigned int keylen, ...)
+{
+ uint32_t bufsize;
+ uint16_t tag;
+ uint32_t ordinal;
+ uint32_t result;
+ unsigned char *enonce;
+ unsigned char *continueflag;
+ unsigned char *authdata;
+ unsigned char testhmac[TPM_HASH_SIZE];
+ unsigned char paramdigest[TPM_HASH_SIZE];
+ struct hash_desc desc;
+ struct scatterlist sg[1];
+ unsigned int dlen;
+ unsigned int dpos;
+ va_list argp;
+ int rc;
+
+ bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
+ tag = LOAD16(buffer, 0);
+ ordinal = command;
+ result = LOAD32N(buffer, TPM_RETURN_OFFSET);
+
+ if (tag == TPM_TAG_RSP_COMMAND)
+ return 0;
+ if (tag != TPM_TAG_RSP_AUTH1_COMMAND)
+ return -1;
+ authdata = buffer + bufsize - TPM_HASH_SIZE;
+ continueflag = authdata - 1;
+ enonce = continueflag - TPM_NONCE_SIZE;
+ rc = init_sha1_desc(&desc);
+ if (rc != 0)
+ return rc;
+ sg_init_one(sg, &result, TPM_U32_SIZE);
+ crypto_hash_update(&desc, sg, TPM_U32_SIZE);
+ sg_init_one(sg, &ordinal, TPM_U32_SIZE);
+ crypto_hash_update(&desc, sg, TPM_U32_SIZE);
+ va_start(argp, keylen);
+ for (;;) {
+ dlen = (unsigned int)va_arg(argp, unsigned int);
+ if (dlen == 0)
+ break;
+ dpos = (unsigned int)va_arg(argp, unsigned int);
+ sg_init_one(sg, buffer + dpos, dlen);
+ crypto_hash_update(&desc, sg, dlen);
+ }
+ va_end(argp);
+ crypto_hash_final(&desc, paramdigest);
+ crypto_free_hash(desc.tfm);
+
+ TSS_rawhmac(testhmac, key, keylen, TPM_HASH_SIZE, paramdigest,
+ TPM_NONCE_SIZE, enonce,
+ TPM_NONCE_SIZE, ononce, 1, continueflag, 0, 0);
+ if (memcmp(testhmac, authdata, TPM_HASH_SIZE) != 0)
+ return -1;
+ return 0;
+}
+
+/*
+ * verify the AUTH2_COMMAND (unseal) result from TPM
+ */
+static uint32_t TSS_checkhmac2(unsigned char *buffer, uint32_t command,
+ unsigned char *ononce, unsigned char *key1,
+ unsigned int keylen1, unsigned char *key2,
+ unsigned int keylen2, ...)
+{
+ uint32_t bufsize;
+ uint16_t tag;
+ uint32_t ordinal;
+ uint32_t result;
+ unsigned char *enonce1;
+ unsigned char *continueflag1;
+ unsigned char *authdata1;
+ unsigned char *enonce2;
+ unsigned char *continueflag2;
+ unsigned char *authdata2;
+ unsigned char testhmac1[TPM_HASH_SIZE];
+ unsigned char testhmac2[TPM_HASH_SIZE];
+ unsigned char paramdigest[TPM_HASH_SIZE];
+ struct hash_desc desc;
+ struct scatterlist sg[1];
+ unsigned int dlen;
+ unsigned int dpos;
+ va_list argp;
+ int rc;
+
+ bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
+ tag = LOAD16(buffer, 0);
+ ordinal = command;
+ result = LOAD32N(buffer, TPM_RETURN_OFFSET);
+
+ if (tag == TPM_TAG_RSP_COMMAND)
+ return 0;
+ if (tag != TPM_TAG_RSP_AUTH2_COMMAND)
+ return -1;
+ authdata1 = buffer + bufsize - (TPM_HASH_SIZE + 1
+ + TPM_HASH_SIZE + TPM_HASH_SIZE);
+ authdata2 = buffer + bufsize - (TPM_HASH_SIZE);
+ continueflag1 = authdata1 - 1;
+ continueflag2 = authdata2 - 1;
+ enonce1 = continueflag1 - TPM_NONCE_SIZE;
+ enonce2 = continueflag2 - TPM_NONCE_SIZE;
+
+ rc = init_sha1_desc(&desc);
+ if (rc != 0)
+ return rc;
+ sg_init_one(sg, &result, TPM_U32_SIZE);
+ crypto_hash_update(&desc, sg, TPM_U32_SIZE);
+ sg_init_one(sg, &ordinal, TPM_U32_SIZE);
+ crypto_hash_update(&desc, sg, TPM_U32_SIZE);
+
+ va_start(argp, keylen2);
+ for (;;) {
+ dlen = (unsigned int)va_arg(argp, unsigned int);
+ if (dlen == 0)
+ break;
+ dpos = (unsigned int)va_arg(argp, unsigned int);
+ sg_init_one(sg, buffer + dpos, dlen);
+ crypto_hash_update(&desc, sg, dlen);
+ }
+ crypto_hash_final(&desc, paramdigest);
+ crypto_free_hash(desc.tfm);
+
+ TSS_rawhmac(testhmac1, key1, keylen1, TPM_HASH_SIZE, paramdigest,
+ TPM_NONCE_SIZE, enonce1,
+ TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0);
+ TSS_rawhmac(testhmac2, key2, keylen2, TPM_HASH_SIZE, paramdigest,
+ TPM_NONCE_SIZE, enonce2,
+ TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0);
+ if (memcmp(testhmac1, authdata1, TPM_HASH_SIZE) != 0)
+ return -1;
+ if (memcmp(testhmac2, authdata2, TPM_HASH_SIZE) != 0)
+ return -1;
+ return 0;
+}
+
+static int trusted_tpm_send(u32 chip_num, unsigned char *cmd, int buflen)
+{
+ int rc;
+
+ dump_tpm_buf(cmd);
+ rc = tpm_send(chip_num, cmd, buflen);
+ dump_tpm_buf(cmd);
+ if (rc > 0)
+ /* Can't return positive return codes values to keyctl */
+ rc = -EPERM;
+ return rc;
+}
+
+static int tpm_reset(struct tpm_buf *tb)
+{
+ INIT_BUF(tb);
+ store16(tb, TPM_TAG_RQU_COMMAND);
+ store32(tb, TPM_RESET_SIZE);
+ store32(tb, TPM_ORD_RESET);
+ return trusted_tpm_send(TPM_ANY_NUM, tb->data, TPM_MAX_BUF_SIZE);
+}
+
+/*
+ * use the TPM random number generator for all new keys and nonces
+ */
+static int tpm_get_random(struct tpm_buf *tb, unsigned char *buf, uint32_t len)
+{
+ int ret = 0;
+
+ INIT_BUF(tb);
+ store16(tb, TPM_TAG_RQU_COMMAND);
+ store32(tb, TPM_GETRANDOM_SIZE);
+ store32(tb, TPM_ORD_GETRANDOM);
+ store32(tb, len);
+ ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, TPM_MAX_BUF_SIZE);
+ memcpy(buf, tb->data + TPM_GETRANDOM_RETURN, len);
+ return ret;
+}
+
+/*
+ * Create an object specific authorisation protocol (OSAP) session
+ */
+static int srkosap(struct tpm_buf *tb, struct osapsess *s)
+{
+ unsigned char enonce[TPM_NONCE_SIZE];
+ unsigned char ononce[TPM_NONCE_SIZE];
+ unsigned char key[TPM_HASH_SIZE];
+ int ret;
+
+ ret = tpm_get_random(tb, ononce, TPM_NONCE_SIZE);
+ if (ret < 0)
+ return ret;
+
+ INIT_BUF(tb);
+ store16(tb, TPM_TAG_RQU_COMMAND);
+ store32(tb, TPM_OSAP_SIZE);
+ store32(tb, TPM_ORD_OSAP);
+ store16(tb, SRKKEYTYPE);
+ store32(tb, SRKHANDLE);
+ storebytes(tb, ononce, TPM_NONCE_SIZE);
+
+ ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, TPM_MAX_BUF_SIZE);
+ if (ret < 0)
+ return ret;
+
+ memset(key, 0, TPM_HASH_SIZE);
+ s->handle = LOAD32(tb->data, TPM_DATA_OFFSET);
+ memcpy(s->enonce, &(tb->data[TPM_DATA_OFFSET + TPM_U32_SIZE]),
+ TPM_NONCE_SIZE);
+ memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + TPM_U32_SIZE +
+ TPM_NONCE_SIZE]), TPM_NONCE_SIZE);
+ ret = TSS_rawhmac(s->secret, key, TPM_HASH_SIZE, TPM_NONCE_SIZE,
+ enonce, TPM_NONCE_SIZE, ononce, 0, 0);
+ return ret;
+}
+
+/*
+ * Create an object independent authorisation protocol (oiap) session
+ */
+static int oiap(struct tpm_buf *tb, uint32_t * handle, unsigned char *nonce)
+{
+ int ret;
+
+ INIT_BUF(tb);
+ store16(tb, TPM_TAG_RQU_COMMAND);
+ store32(tb, TPM_OIAP_SIZE);
+ store32(tb, TPM_ORD_OIAP);
+ ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, TPM_MAX_BUF_SIZE);
+ if (ret < 0)
+ return ret;
+
+ *handle = LOAD32(tb->data, TPM_DATA_OFFSET);
+ memcpy(nonce, &tb->data[TPM_DATA_OFFSET + TPM_U32_SIZE],
+ TPM_NONCE_SIZE);
+ return ret;
+}
+
+/*
+ * Have the TPM seal(encrypt) the trusted key, possibly based on
+ * Platform Configuration Registers (PCRs).
+ */
+static int srkseal(struct tpm_buf *tb,
+ unsigned char *data, int datalen,
+ unsigned char *blob, unsigned int *bloblen,
+ unsigned char *pcrinfo, uint32_t pcrinfosize)
+{
+ struct osapsess sess;
+ unsigned char encauth[TPM_HASH_SIZE];
+ unsigned char pubauth[TPM_HASH_SIZE];
+ unsigned char xorwork[TPM_HASH_SIZE * 2];
+ unsigned char xorhash[TPM_HASH_SIZE];
+ unsigned char dummyauth[TPM_HASH_SIZE];
+ unsigned char nonceodd[TPM_NONCE_SIZE];
+ unsigned char cont;
+ uint32_t ordinal;
+ uint32_t pcrsize;
+ uint32_t datsize;
+ int sealinfosize;
+ int encdatasize;
+ int storedsize;
+ int ret;
+ int i;
+
+ memset(dummyauth, 0, sizeof dummyauth);
+
+ ret = srkosap(tb, &sess);
+ if (ret < 0)
+ return ret;
+ dump_sess(&sess);
+
+ /* calculate encrypted authorization value */
+ memcpy(xorwork, sess.secret, TPM_HASH_SIZE);
+ memcpy(xorwork + TPM_HASH_SIZE, sess.enonce, TPM_HASH_SIZE);
+ ret = TSS_sha1(xorwork, TPM_HASH_SIZE * 2, xorhash);
+ if (ret != 0)
+ return ret;
+
+ ret = tpm_get_random(tb, nonceodd, TPM_NONCE_SIZE);
+ if (ret < 0)
+ return ret;
+ ordinal = htonl(TPM_ORD_SEAL);
+ datsize = htonl(datalen);
+ pcrsize = htonl(pcrinfosize);
+ cont = 0;
+
+ /* encrypt data authorization key */
+ for (i = 0; i < TPM_HASH_SIZE; ++i)
+ encauth[i] = xorhash[i] ^ dummyauth[i];
+
+ /* calculate authorization HMAC value */
+ if (pcrinfosize == 0) {
+ /* no pcr info specified */
+ TSS_authhmac(pubauth, sess.secret, TPM_HASH_SIZE,
+ sess.enonce, nonceodd, cont, TPM_U32_SIZE,
+ &ordinal, TPM_HASH_SIZE, encauth,
+ TPM_U32_SIZE, &pcrsize, TPM_U32_SIZE,
+ &datsize, datalen, data, 0, 0);
+ } else {
+ /* pcr info specified */
+ TSS_authhmac(pubauth, sess.secret, TPM_HASH_SIZE,
+ sess.enonce, nonceodd, cont, TPM_U32_SIZE,
+ &ordinal, TPM_HASH_SIZE, encauth,
+ TPM_U32_SIZE, &pcrsize, pcrinfosize,
+ pcrinfo, TPM_U32_SIZE, &datsize, datalen,
+ data, 0, 0);
+ }
+
+ INIT_BUF(tb);
+ store16(tb, TPM_TAG_RQU_AUTH1_COMMAND);
+ store32(tb, TPM_SEAL_SIZE + pcrinfosize + datalen);
+ store32(tb, TPM_ORD_SEAL);
+ store32(tb, SRKHANDLE);
+ storebytes(tb, encauth, TPM_HASH_SIZE);
+ store32(tb, pcrinfosize);
+ storebytes(tb, pcrinfo, pcrinfosize);
+ store32(tb, datalen);
+ storebytes(tb, data, datalen);
+ store32(tb, sess.handle);
+ storebytes(tb, nonceodd, TPM_NONCE_SIZE);
+ store8(tb, cont);
+ storebytes(tb, pubauth, TPM_HASH_SIZE);
+
+ ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, TPM_MAX_BUF_SIZE);
+ if (ret < 0)
+ return ret;
+
+ /* calculate the size of the returned Blob */
+ sealinfosize = LOAD32(tb->data, TPM_DATA_OFFSET + TPM_U32_SIZE);
+ encdatasize = LOAD32(tb->data, TPM_DATA_OFFSET + TPM_U32_SIZE +
+ TPM_U32_SIZE + sealinfosize);
+ storedsize = TPM_U32_SIZE + TPM_U32_SIZE + sealinfosize +
+ TPM_U32_SIZE + encdatasize;
+
+ /* check the HMAC in the response */
+ ret = TSS_checkhmac1(tb->data, ordinal, nonceodd, sess.secret,
+ TPM_HASH_SIZE, storedsize, TPM_DATA_OFFSET, 0, 0);
+
+ /* copy the returned blob to caller */
+ memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize);
+ *bloblen = storedsize;
+ return ret;
+}
+
+/*
+ * use the AUTH2_COMMAND form of unseal, to authorize both SRK and blob
+ */
+static int srkunseal(struct tpm_buf *tb,
+ unsigned char *blob, int bloblen,
+ unsigned char *data, unsigned int *datalen)
+{
+ unsigned char nonceodd[TPM_NONCE_SIZE];
+ unsigned char dummyauth[TPM_NONCE_SIZE];
+ unsigned char enonce1[TPM_NONCE_SIZE];
+ unsigned char enonce2[TPM_NONCE_SIZE];
+ unsigned char authdata1[TPM_HASH_SIZE];
+ unsigned char authdata2[TPM_HASH_SIZE];
+ uint32_t authhandle1 = 0;
+ uint32_t authhandle2 = 0;
+ unsigned char cont = 0;
+ uint32_t ordinal;
+ uint32_t keyhndl;
+ int ret;
+
+ memset(dummyauth, 0, sizeof dummyauth);
+
+ ret = oiap(tb, &authhandle1, enonce1);
+ if (ret < 0) {
+ pr_info("trusted_key: oiap failed (%d)\n", ret);
+ return ret;
+ }
+ ret = oiap(tb, &authhandle2, enonce2);
+ if (ret < 0) {
+ pr_info("trusted_key: oiap failed (%d)\n", ret);
+ return ret;
+ }
+
+ /* network order for HMAC */
+ ordinal = htonl(TPM_ORD_UNSEAL);
+ keyhndl = htonl(SRKHANDLE);
+ ret = tpm_get_random(tb, nonceodd, TPM_NONCE_SIZE);
+ if (ret < 0) {
+ pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
+ return ret;
+ }
+
+ TSS_authhmac(authdata1, dummyauth, TPM_NONCE_SIZE,
+ enonce1, nonceodd, cont, TPM_U32_SIZE,
+ &ordinal, bloblen, blob, 0, 0);
+ TSS_authhmac(authdata2, dummyauth, TPM_NONCE_SIZE,
+ enonce2, nonceodd, cont, TPM_U32_SIZE,
+ &ordinal, bloblen, blob, 0, 0);
+
+ INIT_BUF(tb);
+ store16(tb, TPM_TAG_RQU_AUTH2_COMMAND);
+ store32(tb, TPM_UNSEAL_SIZE + bloblen);
+ store32(tb, TPM_ORD_UNSEAL);
+ store32(tb, SRKHANDLE);
+ storebytes(tb, blob, bloblen);
+ store32(tb, authhandle1);
+ storebytes(tb, nonceodd, TPM_NONCE_SIZE);
+ store8(tb, cont);
+ storebytes(tb, authdata1, TPM_HASH_SIZE);
+ store32(tb, authhandle2);
+ storebytes(tb, nonceodd, TPM_NONCE_SIZE);
+ store8(tb, cont);
+ storebytes(tb, authdata2, TPM_HASH_SIZE);
+
+ ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, TPM_MAX_BUF_SIZE);
+ if (ret < 0) {
+ pr_info("trusted_key: authhmac failed (%d)\n", ret);
+ return ret;
+ }
+
+ *datalen = LOAD32(tb->data, TPM_DATA_OFFSET);
+ ret = TSS_checkhmac2(tb->data, ordinal, nonceodd,
+ dummyauth, TPM_HASH_SIZE,
+ dummyauth, TPM_HASH_SIZE,
+ TPM_U32_SIZE, TPM_DATA_OFFSET,
+ *datalen, TPM_DATA_OFFSET + TPM_U32_SIZE, 0, 0);
+ if (ret < 0)
+ pr_info("trusted_key: TSS_checkhmac2 failed (%d)\n", ret);
+ memcpy(data, tb->data + TPM_DATA_OFFSET + TPM_U32_SIZE, *datalen);
+ return ret;
+}
+
+/*
+ * Create a new trusted key based on a TPM random number
+ */
+static int key_create(struct trusted_key_payload *p)
+{
+ struct tpm_buf *tb;
+ int ret;
+
+ tb = kzalloc(sizeof *tb, GFP_KERNEL);
+ if (!tb)
+ return -ENOMEM;
+
+ ret = tpm_get_random(tb, p->key, p->key_len);
+ kfree(tb);
+ return ret;
+}
+
+/*
+ * Have the TPM seal(encrypt) the symmetric key
+ */
+static int key_seal(struct trusted_key_payload *p)
+{
+ struct tpm_buf *tb;
+ int ret;
+
+ tb = kzalloc(sizeof *tb, GFP_KERNEL);
+ if (!tb)
+ return -ENOMEM;
+
+ ret = tpm_reset(tb);
+ if (ret < 0) {
+ pr_info("trusted_key: tpm_reset failed (%d)\n", ret);
+ goto out;
+ }
+ ret = srkseal(tb, p->key, p->key_len, p->blob,
+ &p->blob_len, p->pcrinfo, p->pcrinfo_len);
+ if (ret < 0) {
+ pr_info("trusted_key: srkseal failed (%d)\n", ret);
+ goto out;
+ }
+
+out:
+ kfree(tb);
+ return ret;
+}
+
+/*
+ * Have the TPM unseal(decrypt) the symmetric key
+ */
+static int key_unseal(struct trusted_key_payload *p)
+{
+ struct tpm_buf *tb;
+ int ret;
+
+ tb = kzalloc(sizeof *tb, GFP_KERNEL);
+ if (!tb)
+ return -ENOMEM;
+
+ ret = tpm_reset(tb);
+ if (ret < 0) {
+ pr_info("trusted_key: tpm_reset failed (%d)\n", ret);
+ goto out;
+ }
+ ret = srkunseal(tb, p->blob, p->blob_len, p->key, &p->key_len);
+ if (ret < 0)
+ pr_info("trusted_key: srkunseal failed (%d)\n", ret);
+out:
+ kfree(tb);
+ return ret;
+}
+
+enum {
+ Opt_err = -1,
+ Opt_new = 1, Opt_load, Opt_update,
+ Opt_NEW, Opt_LOAD, Opt_UPDATE
+};
+
+static match_table_t key_tokens = {
+ {Opt_new, "new"},
+ {Opt_NEW, "NEW"},
+ {Opt_load, "load"},
+ {Opt_LOAD, "LOAD"},
+ {Opt_update, "update"},
+ {Opt_UPDATE, "UPDATE"},
+ {Opt_err, NULL}
+};
+
+/*
+ * datablob_parse - parse the keyctl data
+ *
+ * datablob format:
+ * "NEW keylen [hex_pcrinfo]"
+ * "LOAD hex_blob"
+ * "UPDATE hex_pcrinfo"
+ *
+ * Tokenizes a copy of the keyctl data, returning a pointer to each token,
+ * which is null terminated.
+ *
+ * On success returns 0, otherwise -EINVAL.
+ */
+static int datablob_parse(char *datablob, char **keylen, char **pcrinfo,
+ char **hex_encoded_data)
+{
+ substring_t args[MAX_OPT_ARGS];
+ int ret = -EINVAL;
+ int key_cmd;
+ char *p;
+
+ p = strsep(&datablob, " \t");
+ if (!p)
+ return ret;
+ key_cmd = match_token(p, key_tokens, args);
+
+ /* All key commands require at least one argument */
+ p = strsep(&datablob, " \t");
+ if (!p)
+ return ret;
+
+ switch (key_cmd) {
+ case Opt_new:
+ case Opt_NEW:
+ *keylen = p;
+ ret = 0;
+ p = strsep(&datablob, " \t");
+ if (p)
+ *pcrinfo = p;
+ break;
+ case Opt_load:
+ case Opt_LOAD:
+ *hex_encoded_data = p;
+ ret = 0;
+ break;
+ case Opt_update:
+ case Opt_UPDATE:
+ *pcrinfo = p;
+ ret = 0;
+ break;
+ case Opt_err:
+ break;
+ }
+ return ret;
+}
+
+/*
+ * Allocate payload.
+ */
+static struct trusted_key_payload *trusted_key_alloc(struct key *key)
+{
+ struct trusted_key_payload *p = NULL;
+ int ret;
+
+ ret = key_payload_reserve(key, sizeof *p);
+ if (ret < 0)
+ return p;
+ p = kzalloc(sizeof *p, GFP_KERNEL);
+ return p;
+}
+
+/*
+ * safety check user inputs and fill in payload
+ */
+static int trusted_key_fill(struct trusted_key_payload *p, char *asc_keylen,
+ char *hex_pcrinfo, char *hex_blob)
+{
+ long key_len;
+ int ret;
+
+ if (hex_blob) {
+ p->blob_len = strlen(hex_blob) / 2;
+ if (p->blob_len > MAX_BLOB_SIZE)
+ return -EINVAL;
+ hex2bin(p->blob, hex_blob, p->blob_len);
+ }
+ if (asc_keylen) {
+ ret = strict_strtol(asc_keylen, 10, &key_len);
+ if ((ret < 0) || (key_len < MIN_KEY_SIZE) ||
+ (key_len > MAX_KEY_SIZE))
+ return -EINVAL;
+ p->key_len = key_len;
+ }
+ if (hex_pcrinfo) {
+ p->pcrinfo_len = strlen(hex_pcrinfo) / 2;
+ if (p->pcrinfo_len > MAX_PCRINFO_SIZE)
+ return -EINVAL;
+ hex2bin(p->pcrinfo, hex_pcrinfo, p->pcrinfo_len);
+ }
+ return 0;
+}
+
+/*
+ * trusted_instantiate - create a new trusted key
+ *
+ * Unseal an existing trusted blob or, for a new key, get a
+ * random key, then seal and create an encryted key-type key,
+ * adding it to the specified keyring.
+ *
+ * On success, return 0. Otherwise return errno.
+ */
+static int trusted_instantiate(struct key *key, const void *data,
+ size_t datalen)
+{
+ struct trusted_key_payload *p = NULL;
+ char *hex_blob = NULL;
+ char *asc_keylen = NULL;
+ char *datablob;
+ char *hex_pcrinfo = NULL;
+ int ret;
+
+ if (datalen <= 0 || datalen > 32767 || !data)
+ return -EINVAL;
+
+ datablob = kzalloc(datalen + 1, GFP_KERNEL);
+ if (!datablob)
+ return -ENOMEM;
+ memcpy(datablob, data, datalen);
+
+ ret = datablob_parse(datablob, &asc_keylen, &hex_pcrinfo, &hex_blob);
+ if (ret < 0)
+ goto out;
+ p = trusted_key_alloc(key);
+ if (!p) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ ret = trusted_key_fill(p, asc_keylen, hex_pcrinfo, hex_blob);
+ if (ret < 0)
+ goto out;
+
+ dump_payload(p);
+
+ if (hex_blob) {
+ ret = key_unseal(p);
+ if (ret < 0)
+ pr_info("trusted_key: key_unseal failed (%d)\n", ret);
+ goto out;
+ }
+
+ if (asc_keylen) {
+ ret = key_create(p);
+ if (ret < 0) {
+ pr_info("trusted_key: key_create failed (%d)\n", ret);
+ goto out;
+ }
+ }
+
+ ret = key_seal(p);
+ if (ret < 0)
+ pr_info("trusted_key: key_seal failed (%d)\n", ret);
+out:
+ if (!ret)
+ rcu_assign_pointer(key->payload.data, p);
+ kfree(datablob);
+ return ret;
+}
+
+static void trusted_rcu_free(struct rcu_head *rcu)
+{
+ struct trusted_key_payload *p;
+
+ p = container_of(rcu, struct trusted_key_payload, rcu);
+ memset(p->key, 0, p->key_len);
+ kfree(p);
+}
+
+/*
+ * trusted_update - reseal an existing key with new PCR values
+ */
+static int trusted_update(struct key *key, const void *data, size_t datalen)
+{
+ struct trusted_key_payload *p = key->payload.data;
+ struct trusted_key_payload *new_p;
+ char *hex_blob = NULL;
+ char *asc_keylen = NULL;
+ char *datablob;
+ char *hex_pcrinfo = NULL;
+ int ret = 0;
+
+ if (datalen <= 0 || datalen > 32767 || !data)
+ return -EINVAL;
+
+ datablob = kzalloc(datalen + 1, GFP_KERNEL);
+ if (!datablob)
+ return -ENOMEM;
+ memcpy(datablob, data, datalen);
+ ret = datablob_parse(datablob, &asc_keylen, &hex_pcrinfo, &hex_blob);
+ if (ret < 0)
+ goto out;
+
+ new_p = trusted_key_alloc(key);
+ if (!new_p) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ ret = trusted_key_fill(new_p, asc_keylen, hex_pcrinfo, hex_blob);
+ if (ret < 0) {
+ pr_info("trusted_key: key_fill failed (%d)\n", ret);
+ kfree(new_p);
+ goto out;
+ }
+
+ /* copy old key values, and reseal with new pcrs */
+ new_p->key_len = p->key_len;
+ memcpy(new_p->key, p->key, p->key_len);
+ dump_payload(p);
+ dump_payload(new_p);
+
+ ret = key_seal(new_p);
+ if (ret < 0) {
+ pr_info("trusted_key: key_seal failed (%d)\n", ret);
+ kfree(new_p);
+ goto out;
+ }
+ rcu_assign_pointer(key->payload.data, new_p);
+ call_rcu(&p->rcu, trusted_rcu_free);
+out:
+ kfree(datablob);
+ return ret;
+}
+
+/*
+ * trusted_read - copy the sealed blob data to userspace in hex.
+ * On success, return to userspace the trusted key datablob size.
+ */
+static long trusted_read(const struct key *key, char __user * buffer,
+ size_t buflen)
+{
+ struct trusted_key_payload *p;
+ char *ascii_buf;
+ char *bufp;
+ int i;
+
+ p = rcu_dereference_protected(key->payload.data,
+ rwsem_is_locked(&((struct key *)key)->sem));
+ if (!p)
+ return -EINVAL;
+
+ if (!buffer || buflen <= 0)
+ return 2 * p->blob_len;
+
+ ascii_buf = kzalloc(2 * p->blob_len, GFP_KERNEL);
+ if (!ascii_buf)
+ return -ENOMEM;
+
+ bufp = ascii_buf;
+ for (i = 0; i < p->blob_len; i++)
+ bufp = pack_hex_byte(bufp, p->blob[i]);
+
+ if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) {
+ kfree(ascii_buf);
+ return -EFAULT;
+ }
+ kfree(ascii_buf);
+ return 2 * p->blob_len;
+}
+
+/*
+ * trusted_destroy - before freeing the key, clear the decrypted data
+ */
+static void trusted_destroy(struct key *key)
+{
+ struct trusted_key_payload *p = key->payload.data;
+
+ if (!p)
+ return;
+ memset(p->key, 0, p->key_len);
+ kfree(key->payload.data);
+}
+
+struct key_type key_type_trusted = {
+ .name = "trusted",
+ .instantiate = trusted_instantiate,
+ .update = trusted_update,
+ .match = user_match,
+ .destroy = trusted_destroy,
+ .describe = user_describe,
+ .read = trusted_read,
+};
+EXPORT_SYMBOL_GPL(key_type_trusted);
+
+static int __init init_trusted(void)
+{
+ int ret;
+
+ ret = register_key_type(&key_type_trusted);
+ if (ret < 0)
+ return ret;
+ return ret;
+}
+
+static void __exit cleanup_trusted(void)
+{
+ unregister_key_type(&key_type_trusted);
+}
+
+module_init(init_trusted);
+module_exit(cleanup_trusted);
+
+MODULE_LICENSE("GPL");
diff --git a/security/keys/trusted_defined.h b/security/keys/trusted_defined.h
new file mode 100644
index 0000000..e2d0c11
--- /dev/null
+++ b/security/keys/trusted_defined.h
@@ -0,0 +1,125 @@
+#ifndef __TRUSTED_KEY_H
+#define __TRUSTED_KEY_H
+
+#define TPM_MAX_BUF_SIZE 512
+#define TPM_TAG_RQU_COMMAND 193
+#define TPM_TAG_RQU_AUTH1_COMMAND 194
+#define TPM_TAG_RQU_AUTH2_COMMAND 195
+#define TPM_TAG_RSP_COMMAND 196
+#define TPM_TAG_RSP_AUTH1_COMMAND 197
+#define TPM_TAG_RSP_AUTH2_COMMAND 198
+#define TPM_NONCE_SIZE 20
+#define TPM_HASH_SIZE 20
+#define TPM_SIZE_OFFSET 2
+#define TPM_RETURN_OFFSET 6
+#define TPM_DATA_OFFSET 10
+#define TPM_U32_SIZE 4
+#define TPM_GETRANDOM_SIZE 14
+#define TPM_GETRANDOM_RETURN 14
+#define TPM_ORD_GETRANDOM 70
+#define TPM_RESET_SIZE 10
+#define TPM_ORD_RESET 90
+#define TPM_OSAP_SIZE 36
+#define TPM_ORD_OSAP 11
+#define TPM_OIAP_SIZE 10
+#define TPM_ORD_OIAP 10
+#define TPM_SEAL_SIZE 87
+#define TPM_ORD_SEAL 23
+#define TPM_ORD_UNSEAL 24
+#define TPM_UNSEAL_SIZE 104
+#define SRKKEYTYPE 4
+#define SRKHANDLE 0x40000000
+#define TPM_ANY_NUM 0xFFFF
+
+#define MIN_KEY_SIZE 32
+
+#define LOAD32(buffer, offset) (ntohl(*(uint32_t *)&buffer[offset]))
+#define LOAD32N(buffer, offset) (*(uint32_t *)&buffer[offset])
+#define LOAD16(buffer, offset) (ntohs(*(uint16_t *)&buffer[offset]))
+
+struct tpm_buf {
+ int len;
+ unsigned char data[TPM_MAX_BUF_SIZE];
+};
+
+#define INIT_BUF(tb) (tb->len = 0)
+
+struct osapsess {
+ uint32_t handle;
+ unsigned char secret[TPM_HASH_SIZE];
+ unsigned char enonce[TPM_NONCE_SIZE];
+};
+
+#define TPM_DEBUG 0
+
+#if TPM_DEBUG
+static inline void dump_payload(struct trusted_key_payload *p)
+{
+ pr_info("trusted_key: key_len %d\n", p->key_len);
+ print_hex_dump(KERN_INFO, "key ", DUMP_PREFIX_NONE,
+ 16, 1, p->key, p->key_len, 0);
+ pr_info("trusted_key: pcrinfo %d\n", p->pcrinfo_len);
+ print_hex_dump(KERN_INFO, "pcrinfo ", DUMP_PREFIX_NONE,
+ 16, 1, p->pcrinfo, p->pcrinfo_len, 0);
+ pr_info("trusted_key: bloblen %d\n", p->blob_len);
+ print_hex_dump(KERN_INFO, "blob ", DUMP_PREFIX_NONE,
+ 16, 1, p->blob, p->blob_len, 0);
+}
+
+static inline void dump_sess(struct osapsess *s)
+{
+ print_hex_dump(KERN_INFO, "trusted-key: handle", DUMP_PREFIX_NONE,
+ 16, 1, &s->handle, 4, 0);
+ pr_info("trusted-key: secret:\n");
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
+ 16, 1, &s->secret, TPM_HASH_SIZE, 0);
+ pr_info("trusted-key: enonce:\n");
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE,
+ 16, 1, &s->enonce, TPM_HASH_SIZE, 0);
+}
+
+static inline void dump_tpm_buf(unsigned char *buf)
+{
+ int len;
+
+ pr_info("\ntrusted-key: tpm buffer\n");
+ len = LOAD32(buf, TPM_SIZE_OFFSET);
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);
+}
+#else
+static inline void dump_payload(struct trusted_key_payload *p)
+{
+}
+
+static inline void dump_sess(struct osapsess *s)
+{
+}
+
+static inline void dump_tpm_buf(unsigned char *buf)
+{
+}
+#endif
+
+static inline void store8(struct tpm_buf *buf, unsigned char value)
+{
+ buf->data[buf->len++] = value;
+}
+
+static inline void store16(struct tpm_buf *buf, uint16_t value)
+{
+ *(uint16_t *) & buf->data[buf->len] = htons(value);
+ buf->len += sizeof(value);
+}
+
+static inline void store32(struct tpm_buf *buf, uint32_t value)
+{
+ *(uint32_t *) & buf->data[buf->len] = htonl(value);
+ buf->len += sizeof(value);
+}
+
+static inline void storebytes(struct tpm_buf *buf, unsigned char *in, int len)
+{
+ memcpy(buf->data + buf->len, in, len);
+ buf->len += len;
+}
+#endif
--
1.7.2.2
^ permalink raw reply related
* [PATCH v1 0/4] keys: trusted and encrypted keys
From: Mimi Zohar @ 2010-10-07 20:52 UTC (permalink / raw)
To: linux-kernel
Cc: Mimi Zohar, linux-security-module, keyrings, linux-crypto,
David Howells, James Morris, David Safford, Rajiv Andrade
Since the original posting, the encrypted keys are started at
late_initcall, in order to wait for the crypto API to be
initialized, minor changes were made to Kconfig, and the
TPM Maintainer acked the second patch.
Trusted and Encrypted Keys are two new key types added to the
existing kernel key ring service. Both of these new types are
variable length symmetic keys, and in both cases all keys are
created in the kernel, and user space sees, stores, and loads
only encrypted blobs. Trusted Keys require the availability of a
Trusted Platform Module (TPM) chip for greater security, while
Encrypted Keys can be used on any system. All user level blobs,
are displayed and loaded in hex ascii for convenience, and
are integrity verified.
Trusted Keys use a TPM both to generate and to seal the keys.
Keys are sealed under a 2048 bit RSA key in the TPM, and optionally
sealed to specified PCR (integrity measurement) values, and only
unsealed by the TPM, if PCRs and blob integrity verifications match.
A loaded Trusted Key can be updated with new (future) PCR values,
so keys are easily migrated to new pcr values, such as when the
kernel and initramfs are updated. The same key can have many
saved blobs under different PCR values, so multiple boots are
easily supported.
Trusted Keys are sealed under the SRK, which must have the default
authorization value (20 zeros). This can be set at takeownership
time with the trouser's utility "tpm_takeownership -u -z".
Usage:
keyctl add trusted name "NEW keylen [hex_pcrinfo]" ring
keyctl add trusted name "LOAD hex_blob" ring
keyctl update key "UPDATE hex_pcrinfo"
keyctl print keyid
keyctl pipe keyid > filename
The key length for new keys are always in bytes.
Trusted Keys can be 32 - 128 bytes (256 - 1024 bits), the upper
limit is to fit within the 2048 bit SRK (RSA) keylength, with
all necessary structure/padding. The keywords NEW, LOAD, and
UPDATE can be all upper or all lower case.
Encrypted keys do not depend on a TPM, and are faster, as they
use AES for encryption/decryption. New keys are created from kernel
generated random numbers, and are encrypted/decrypted using a
specified 'master' key. The 'master' key can either be a trusted-key
or user-key type. The main disadvantage of encrypted keys is that if
they are not rooted in a trusted key, they are only as secure as the
user key encrypting them. The master user key should therefore
be loaded in as secure a way as possible, preferably early in
boot.
Usage:
keyctl add encrypted name "NEW master-key-name keylen" ring
keyctl add encrypted name "LOAD master-key-name keylen hex_blob" ring
keyctl update keyid "UPDATE master-key-name"
The initial consumer of trusted keys is EVM, which at boot time
needs a high quality symmetric key for HMAC protection of file
metadata. The use of a trusted key provides strong guarantees
that the EVM key has not been compromised by a user level problem,
and when sealed to specific boot PCR values, protects against
boot and offline attacks. Other uses for trusted and encrypted
keys, such as for disk and file encryption are anticipated.
Mimi Zohar
Dave Safford
Mimi Zohar (4):
lib: hex2bin converts ascii hexadecimal string to binary
key: add tpm_send command
keys: add new trusted key-type
keys: add new key-type encrypted
drivers/char/tpm/tpm.c | 17 +
include/keys/encrypted-type.h | 30 ++
include/keys/trusted-type.h | 33 ++
include/linux/kernel.h | 1 +
include/linux/tpm.h | 3 +
lib/hexdump.c | 16 +
security/Kconfig | 31 ++
security/keys/Makefile | 2 +
security/keys/encrypted_defined.c | 782 +++++++++++++++++++++++++++++
security/keys/encrypted_defined.h | 52 ++
security/keys/trusted_defined.c | 997 +++++++++++++++++++++++++++++++++++++
security/keys/trusted_defined.h | 125 +++++
12 files changed, 2089 insertions(+), 0 deletions(-)
create mode 100644 include/keys/encrypted-type.h
create mode 100644 include/keys/trusted-type.h
create mode 100644 security/keys/encrypted_defined.c
create mode 100644 security/keys/encrypted_defined.h
create mode 100644 security/keys/trusted_defined.c
create mode 100644 security/keys/trusted_defined.h
--
1.7.2.2
^ permalink raw reply
* [PATCH v1 2/4] key: add tpm_send command
From: Mimi Zohar @ 2010-10-07 20:52 UTC (permalink / raw)
To: linux-kernel
Cc: Mimi Zohar, linux-security-module, keyrings, linux-crypto,
David Howells, James Morris, David Safford, Rajiv Andrade
In-Reply-To: <1286484734-3119-1-git-send-email-zohar@linux.vnet.ibm.com>
Add internal kernel tpm_send() command used to seal/unseal keys.
Signed-off-by: David Safford <safford@watson.ibm.com>
Reviewd-by: Mimi Zohar <zohar@watson.ibm.com>
Acked-by: Rajiv Andrade <srajiv@linux.vnet.ibm.com>
---
drivers/char/tpm/tpm.c | 17 +++++++++++++++++
include/linux/tpm.h | 3 +++
2 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 7c41335..5987d9c 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -780,6 +780,23 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
}
EXPORT_SYMBOL_GPL(tpm_pcr_extend);
+int tpm_send(u32 chip_num, char *cmd, int buflen)
+{
+ struct tpm_chip *chip;
+ int rc;
+
+ chip = tpm_chip_find_get(chip_num);
+ if (chip == NULL)
+ return -ENODEV;
+
+ rc = transmit_cmd(chip, (struct tpm_cmd_t *)cmd, buflen,
+ "attempting tpm_cmd");
+
+ module_put(chip->dev->driver->owner);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_send);
+
ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
char *buf)
{
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index ac5d1c1..a0ecaa9 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -31,6 +31,7 @@
extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
+extern int tpm_send(u32 chip_num, char *cmd, int buflen);
#else
static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
return -ENODEV;
@@ -38,5 +39,7 @@ static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
static inline int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) {
return -ENODEV;
}
+static inline int tpm_send(u32 chip_num, char *cmd, int buflen) {
+ return -ENODEV;
#endif
#endif
--
1.7.2.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.