Mailing List Archive

die() required on pax-mark?
Due to my own stupidity (forgot to mount ext3 with -o user_xattr), I
noticed that many ebuilds call pax-mark without a corresponding "||
die". Since pax-mark returns non-zero on failure, does not die itself,
and is most likely required for the package to work, it seems like the
'die' should be there.

Agreed? I could start filing bugs against the individual packages. The
eclass docs are pretty clear to me, but maybe @hardened can add a note
that 'die' is required on pax-mark?

Or perhaps the function should die on its own? I believe the error
message would be consistent; it might not make sense to add the same
'die' to every ebuild.
Re: die() required on pax-mark? [ In reply to ]
On 10/19/2013 02:20 PM, Michael Orlitzky wrote:
> Due to my own stupidity (forgot to mount ext3 with -o user_xattr), I
> noticed that many ebuilds call pax-mark without a corresponding "||
> die". Since pax-mark returns non-zero on failure, does not die itself,
> and is most likely required for the package to work, it seems like the
> 'die' should be there.
>
> Agreed? I could start filing bugs against the individual packages. The
> eclass docs are pretty clear to me, but maybe @hardened can add a note
> that 'die' is required on pax-mark?
>
> Or perhaps the function should die on its own? I believe the error
> message would be consistent; it might not make sense to add the same
> 'die' to every ebuild.
>

Can you check to see if the || die is required only on packages before
EAPI = 5? Or is it on all EAPI versions?

Having said that, I'm not sure we want the ebuild to fail just because
pax-mark fails. People on vanilla profiles without xattr support will
be annoyed.

--
Anthony G. Basile, Ph. D.
Chair of Information Technology
D'Youville College
Buffalo, NY 14201
(716) 829-8197
Re: die() required on pax-mark? [ In reply to ]
On 10/19/2013 08:29 PM, Anthony G. Basile wrote:
>
> Can you check to see if the || die is required only on packages before
> EAPI = 5? Or is it on all EAPI versions?

It's required anywhere you want the ebuild to die when pax-mark fails.
AFAIK, the EAPI >= 4 auto-die behavior only applies to the commands
listed in the PMS under "Ebuild-specific Commands".


> Having said that, I'm not sure we want the ebuild to fail just because
> pax-mark fails. People on vanilla profiles without xattr support will
> be annoyed.

Can this be done in the profiles instead of the eclass?

Right now, the eclass sets PAX_MARKINGS="PT" for everyone when the
variable is unset. On hardened, we probably want PAX_MARKINGS="PT" for
now, PAX_MARKINGS="PT XT" later, and PAX_MARKINGS="XT" eventually.

Non-hardened users don't care about the markings[1], so it doesn't
matter to them whether or not pax-mark fails. But for hardened users,
the package will be broken, so the ebuild should die.

What would happen it we changed the line,

PAX_MARKINGS=${PAX_MARKINGS:="PT"}

in the eclass, to,

PAX_MARKINGS=${PAX_MARKINGS:="none"}

and added,

PAX_MARKINGS="PT"

to the hardened make.defaults?



[1] There may be exceptions to this rule, but if we remove the PT
default for non-hardened users, they can still set PAX_MARKINGS in
make.conf if they want the markings.
Re: die() required on pax-mark? [ In reply to ]
On 10/19/2013 08:56 PM, Michael Orlitzky wrote:
> On 10/19/2013 08:29 PM, Anthony G. Basile wrote:
>>
>> Can you check to see if the || die is required only on packages before
>> EAPI = 5? Or is it on all EAPI versions?
>
> It's required anywhere you want the ebuild to die when pax-mark fails.
> AFAIK, the EAPI >= 4 auto-die behavior only applies to the commands
> listed in the PMS under "Ebuild-specific Commands".
>
>
>> Having said that, I'm not sure we want the ebuild to fail just because
>> pax-mark fails. People on vanilla profiles without xattr support will
>> be annoyed.
>
> Can this be done in the profiles instead of the eclass?
>
> Right now, the eclass sets PAX_MARKINGS="PT" for everyone when the
> variable is unset. On hardened, we probably want PAX_MARKINGS="PT" for
> now, PAX_MARKINGS="PT XT" later, and PAX_MARKINGS="XT" eventually.
>
> Non-hardened users don't care about the markings[1], so it doesn't
> matter to them whether or not pax-mark fails. But for hardened users,
> the package will be broken, so the ebuild should die.
>
> What would happen it we changed the line,
>
> PAX_MARKINGS=${PAX_MARKINGS:="PT"}
>
> in the eclass, to,
>
> PAX_MARKINGS=${PAX_MARKINGS:="none"}
>
> and added,
>
> PAX_MARKINGS="PT"
>
> to the hardened make.defaults?
>
>
>
> [1] There may be exceptions to this rule, but if we remove the PT
> default for non-hardened users, they can still set PAX_MARKINGS in
> make.conf if they want the markings.
>

The profile idea is a good one, but I'm always worried about people who
switch profiles. If we don't do the markings on *all* gentoo systems,
then someone switching from vanilla to hardened may have to re-emerge
lots of packages. Unlike PT_PAX which is guaranteed to be there for
systems compiled on gentoo, XT_PAX markings are more fragile and depend
on the filesystem being able to sustain them.



--
Anthony G. Basile, Ph. D.
Chair of Information Technology
D'Youville College
Buffalo, NY 14201
(716) 829-8197
Re: die() required on pax-mark? [ In reply to ]
On 10/20/2013 07:39 PM, Anthony G. Basile wrote:
>
> The profile idea is a good one, but I'm always worried about people who
> switch profiles. If we don't do the markings on *all* gentoo systems,
> then someone switching from vanilla to hardened may have to re-emerge
> lots of packages. Unlike PT_PAX which is guaranteed to be there for
> systems compiled on gentoo, XT_PAX markings are more fragile and depend
> on the filesystem being able to sustain them.
>


I thought about this, but it isn't as bad as it looks initially.

As long as we have PT_PAX, there's nothing to worry about. Even with a
profile-based solution, we could set PAX_MARKINGS="PT" in the base
make.defaults. So no problem for now.

But eventually, we're going to drop PT_PAX in favor of XT_PAX. As I
mentioned, many ebuilds in the tree are calling "pax-mark || die". That
will block the switch, since packages would begin to fail for users
without xattr support. There are two obvious ways to fix it: remove the
die calls, or implement a profile-based solution that doesn't annoy
non-hardened users. So maybe we have to implement a profile-based
solution anyway, and the point is moot.

But lets say for the sake of argument that everyone removes the "|| die"
from their pax-marks. We still have two cases:

1. The users that have xattr-enabled filesystems. They can switch
to hardened freely, since the pax-marks have been succeeding.

But are you *sure* you've had xattrs enabled the entire time we've
been doing XT_PAX markings?

a. If so, great.

b. If not, you'd better `emerge -e world` anyway to avoid
surprises.

2. Users without xattr support. The calls to pax-mark didn't do
anything, but they didn't fail. A full `emerge -e world` is
necessary to avoid mysterious breakage.

This is in contrast to the profile-based solution, which only has one
case: everybody has to `emerge -e world` once to get the markings. But,
after we drop PT_PAX, this is only *worse* for the people in (1.a).
That's a much smaller group than /everyone/ who switches to hardened.
Re: die() required on pax-mark? [ In reply to ]
> But, after we drop PT_PAX, this is only *worse* for the people in
> (1.a). That's a much smaller group than /everyone/ who switches to
> hardened.

There seems to be the theoretical possibility of dropping XT_PAX instead
of PT_PAX. The correct work of PAX markings would then not depend on the
file system used. Therefore users with and without capable file systems
could switch to hardened freely, since all the pax-markings would have
been succeessfully applied to the executables.

I am only a user of Gentoo Hardened (amd64) and do not know, why that
option seems would not be a viable path.
Is it because of self-checking binary blobs?
Perhaps, it should be at least a valid choice to not drop (legacy?)
PT_PAX markings - just in case you want to use hardened without xattr or
want to upgrade from vanilla.



--
Allan Wegan
Re: die() required on pax-mark? [ In reply to ]
On Sun, 20 Oct 2013 19:39:10 -0400
"Anthony G. Basile" <basile@opensource.dyc.edu> wrote:

> On 10/19/2013 08:56 PM, Michael Orlitzky wrote:
> > On 10/19/2013 08:29 PM, Anthony G. Basile wrote:
> >>
> >> Can you check to see if the || die is required only on packages
> >> before EAPI = 5? Or is it on all EAPI versions?
> >
> > It's required anywhere you want the ebuild to die when pax-mark
> > fails. AFAIK, the EAPI >= 4 auto-die behavior only applies to the
> > commands listed in the PMS under "Ebuild-specific Commands".
> >
> >
> >> Having said that, I'm not sure we want the ebuild to fail just
> >> because pax-mark fails. People on vanilla profiles without xattr
> >> support will be annoyed.
> >
> > Can this be done in the profiles instead of the eclass?
> >
> > Right now, the eclass sets PAX_MARKINGS="PT" for everyone when the
> > variable is unset. On hardened, we probably want PAX_MARKINGS="PT"
> > for now, PAX_MARKINGS="PT XT" later, and PAX_MARKINGS="XT"
> > eventually.
> >
> > Non-hardened users don't care about the markings[1], so it doesn't
> > matter to them whether or not pax-mark fails. But for hardened
> > users, the package will be broken, so the ebuild should die.
> >
> > What would happen it we changed the line,
> >
> > PAX_MARKINGS=${PAX_MARKINGS:="PT"}
> >
> > in the eclass, to,
> >
> > PAX_MARKINGS=${PAX_MARKINGS:="none"}
> >
> > and added,
> >
> > PAX_MARKINGS="PT"
> >
> > to the hardened make.defaults?
> >
> >
> >
> > [1] There may be exceptions to this rule, but if we remove the PT
> > default for non-hardened users, they can still set PAX_MARKINGS in
> > make.conf if they want the markings.
> >
>
> The profile idea is a good one, but I'm always worried about people
> who switch profiles. If we don't do the markings on *all* gentoo
> systems, then someone switching from vanilla to hardened may have to
> re-emerge lots of packages. Unlike PT_PAX which is guaranteed to be
> there for systems compiled on gentoo, XT_PAX markings are more
> fragile and depend on the filesystem being able to sustain them.
>
>
>

I will just note that people changing profile usually should rebuild
world anyway, to have everything build with hardened toolchain.
So maybe just add another step to hardened guide, like reboot into
xattr enabled kernel before building stuff.
Re: die() required on pax-mark? [ In reply to ]
On 10/21/2013 03:03 AM, Allan Wegan wrote:
>
>> But, after we drop PT_PAX, this is only *worse* for the people in
>> (1.a). That's a much smaller group than /everyone/ who switches to
>> hardened.
>
> There seems to be the theoretical possibility of dropping XT_PAX instead
> of PT_PAX. The correct work of PAX markings would then not depend on the
> file system used. Therefore users with and without capable file systems
> could switch to hardened freely, since all the pax-markings would have
> been succeessfully applied to the executables.
>
> I am only a user of Gentoo Hardened (amd64) and do not know, why that
> option seems would not be a viable path.
> Is it because of self-checking binary blobs?

Yes and things like the programming language 'go' who's linker did not
produce a PAX_FLAGS program header --- it does now after we got upstream
to add it etc. The problem is that a PAX_FLAGS program header is not
standard while user defined xattrs are. eg. EI_PAX used to put the
markers in the ELF header (in a non-standard way) until that got
clobbered by a commit in glibc; similarly pax markings in the program
header cause issue in cases like the above. XT_PAX has the advantage of
not violating a standard while the disadvantage of needing end-to-end
xattr support.

Pick your poison.


> Perhaps, it should be at least a valid choice to not drop (legacy?)
> PT_PAX markings - just in case you want to use hardened without xattr or
> want to upgrade from vanilla.
>

I have no intentions of dropping PT_PAX anytime soon. toolchain did
indicate a desire to do so because the program header causes issues in
binutils' test suite, but dropping PT_AX is a long range plan if it will
ever happen.

The current issue, in my opinion, is how to spead up the install wrapper
which is written in python and slow as hell.

--
Anthony G. Basile, Ph. D.
Chair of Information Technology
D'Youville College
Buffalo, NY 14201
(716) 829-8197
Re: die() required on pax-mark? [ In reply to ]
> The problem is that a PAX_FLAGS program header is not
> standard while user defined xattrs are. eg. EI_PAX used to put the
> markers in the ELF header (in a non-standard way) until that got
> clobbered by a commit in glibc; similarly pax markings in the program
> header cause issue in cases like the above. XT_PAX has the advantage
> of not violating a standard while the disadvantage of needing
> end-to-end xattr support.

I think the issue here is not, that a non-standard way is used. It is,
that the best way to use PAX markings is not standardized. It should be
added to the ELF standard (in a generalized way, so that other runtime
exploit mitigation suites could use that standard too).

I do not know, whether there are valid use cases for using PAX-marked
binaries on non-xattr-capable file systems. It just feels like that
markings belong more to the binary itself than to the reference to that
binary in the file system.

> I have no intentions of dropping PT_PAX anytime soon. toolchain did
> indicate a desire to do so because the program header causes issues in
> binutils' test suite, but dropping PT_AX is a long range plan if it
> will ever happen.

I am relieved to read that. So i do not have to rebuild the kernels yet
(i may have configured Grsec to only use the markings in the ELF header
- but i am not sure about that).

> The current issue, in my opinion, is how to spead up the install
> wrapper which is written in python and slow as hell.

Has the bottleneck already been identified? Python should not be much
slower than other languages for solving mostly IO-based problems.



--
Allan Wegan
Jabber: allanwegan@erdor.de
ICQ: 209459114
Re: die() required on pax-mark? [ In reply to ]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 10/22/2013 08:38 AM, Allan Wegan wrote:
>
> Has the bottleneck already been identified? Python should not be
> much slower than other languages for solving mostly IO-based
> problems.

When you emerge something with a bazillion files, the install wrapper
(and thus the python interpreter) get launched that many times. It's
the startup time that kills it.

I tried to write a 'cp' wrapper once for a similar reason (it doesn't
preserve posix ACLs), and it's not as easy as it sounds to just
"rewrite it in C" or do the PAX markings after 'install'. The problem
you run into is that it's very difficult to figure out where 'install'
put the file without reimplementing all of 'install'.

But we do have an advantage in portage: we sandbox things before
moving them to the real filesystem, so portage actually knows all of
the files that will got 'install'ed and where they'll wind up. If we
sandbox the PAX markings as well, it should be possible to hit those
files with paxctl-ng after they've been moved to the real root.

I believe the sandbox option is what Anthony listed here as option #4:

https://bugs.gentoo.org/show_bug.cgi?id=465000

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.20 (GNU/Linux)

iQIcBAEBAgAGBQJSZn3cAAoJEBxJck0inpOi/bQP/2w8+bDmVA6eFLa7Tc35vyxY
8B/N2Ya0Nu1VLG2mbmnEFUKiQxK6I3QNbYckeRqB3g5/6tp4Pp83s0xWQQbcygH+
NhOjCme92JVloYA+Ux8XgC1DF6Ys5cgMFhGpWN4ZH7lsufk21p4CPz5v0yODH32Z
lFKqqokeh0EVfHKQYNa/nI65iW/Nz5Dbj1cKqhInZQM7z01fi7Dpy6ZLaQQ3hZyj
2GM8zXPqjGEgVmXf8oHDIbTOnD6//P5n3mWQb1thmb8wIXL7Uyx8lBNa2LkaoA86
q86GxcV6YYed5AEVDdwm+4IWF3bILrsaP4Vm5S5lpUvmfEZqoECwtfxoU2CUHcjO
KK2+py10msyV4JUEGxGZCK/u3NJ9h1aQ4e/KvwTa9JBzVwzcaSS7fyHlGpkRFlgh
7vh7Ju91sWz0xH+Uwpt3mwGBPcYoG9LBndCGAgzKRF/uVPZoItX+X4mWo3/2DcEq
FqnS6UeWQhew175jRD0TyV2sFODL9isfy37o36ZGLc6LxDShB9v1XQ5aF3VfrlhJ
le8u3dC8PoFg4nTy3tL30gf3J65Ms4itdi9MoYrDAL0oNktPXx97erje1QobiViN
rQYm4ZKPinEQDDFNP3d2OTXuk6hJclzYgfFxm+uz2EW+NRZn955IbkKmCIQq00I8
e7XMKUgkBOR5L/l5wra6
=kbgW
-----END PGP SIGNATURE-----
Re: die() required on pax-mark? [ In reply to ]
> When you emerge something with a bazillion files, the install wrapper
> (and thus the python interpreter) get launched that many times. It's
> the startup time that kills it.

Should that PAX markings not only be neccessary for a few hand-selected
binaries that refuse to work with secure-by-default settings?
I remember setting PAX-markings by hand (a year or so ago) for a few
binaries that would else crash with Grsec loglines. I did not had the
impression, that there are much of them (that where mostly games, i admit).



--
Allan Wegan
Jabber: allanwegan@erdor.de
ICQ: 209459114
Re: die() required on pax-mark? [ In reply to ]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 10/22/2013 03:08 PM, Allan Wegan wrote:
>> When you emerge something with a bazillion files, the install
>> wrapper (and thus the python interpreter) get launched that many
>> times. It's the startup time that kills it.
>
> Should that PAX markings not only be neccessary for a few
> hand-selected binaries that refuse to work with secure-by-default
> settings? I remember setting PAX-markings by hand (a year or so
> ago) for a few binaries that would else crash with Grsec loglines.
> I did not had the impression, that there are much of them (that
> where mostly games, i admit).

Yes, and it should be possible to "write down" which binaries got
pax-marked, and only use the python install wrapper for those
particular files.

But, there is an underlying problem that it would be nice to solve at
the same time. It should be possible to set any sort of xattrs (not
just PAX!) in an ebuild and have them correctly copied to the live
filesystem during an emerge. For this to work, we have to handle the
case where a developer (or an upstream makefile) calls setfattr
manually on some files. When FEATURES="xattr" is set, portage uses the
wrapper to install /every/ file, ostensibly for this case.

The other way to handle it would be to check whether or not some file
has xattrs, and use the regular 'install' if it doesn't. But how do
you implement that? You'd either have to hack portage, or write some
sort of wrapper...

There's already a hack in portage to support xattrs, so maybe that
would work, who knows. I'm in over my head here.


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.20 (GNU/Linux)

iQIcBAEBAgAGBQJSZtRsAAoJEBxJck0inpOiz7AQAJIW8wrNorRl8YOjAOlTpoq/
rerZ2IIpyYYg6uB9fotEcJYtmiinClX4Yf3crl2tyqLZLlQJUFrIM+A90LdNAdXY
wYbf5R9HpMxhNsTVKb4sP/ErZzktVOf26kyjzPlql+P/ICk0NYO+YgAswJI4b5L9
trVuraFPwPQGEDDEq5Ep8+9Mm6rBgAj95HlZHIChKVR0zB7jKL372z3QemeFS1sO
Hc7YDZvlwb1U9Ab/EK7qy1aqTZg6Zrzn/wslyZo+tpnJ+aCJENXGDXWh678LDDTP
BnKXsTjNkMXs+fmRfkL2ivIJNs8dYIlcTZ4rBotdBgXQ+fusRuyKXQe3CbyjMzjV
7V8s+aMj31QN29MbQ33zDIEdDyuhulXv4SpxZQfYyRn7ZBdmz2AxSABySQA7DzvJ
OVwe6jRd7Zm272STBj0Agnf2ct6F0KRsC+gPl2COY9y+sV90BzquCsDYB4Z6ybX4
6Ttl/oAxVYjWZNu669TFxeiiga0FhjLVOTvaCJdXrva97iZsssjJFPJcCVSx/IKQ
gu2WbZDX5yx0/TYNRIrqZ8MDB49sCMSLktvjJoOoEydaBDCv6X3y+zvVuR/OCElV
DHdNRi25shztbQTZamgQdQLKOluTEPZ4gkAKH5jUHrg70cfQMG1HXMZFqC64aSi8
lUkJE3WYhuXJX9S6RvDE
=G/D/
-----END PGP SIGNATURE-----
Re: die() required on pax-mark? [ In reply to ]
On 10/22/2013 03:39 PM, Michael Orlitzky wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On 10/22/2013 03:08 PM, Allan Wegan wrote:
>>> When you emerge something with a bazillion files, the install
>>> wrapper (and thus the python interpreter) get launched that many
>>> times. It's the startup time that kills it.
>>
>> Should that PAX markings not only be neccessary for a few
>> hand-selected binaries that refuse to work with secure-by-default
>> settings? I remember setting PAX-markings by hand (a year or so
>> ago) for a few binaries that would else crash with Grsec loglines.
>> I did not had the impression, that there are much of them (that
>> where mostly games, i admit).
>
> Yes, and it should be possible to "write down" which binaries got
> pax-marked, and only use the python install wrapper for those
> particular files.
>
> But, there is an underlying problem that it would be nice to solve at
> the same time. It should be possible to set any sort of xattrs (not
> just PAX!) in an ebuild and have them correctly copied to the live
> filesystem during an emerge.

My motivation here was beyond just user.pax.flags. Right now the
install.py wrapper only does XT_PAX flags, ie the user.pax.flags
namespace, but it should be able to do any extended attribute namespace.
I'm trying to pave the way for full end-to-end extended attribute support.

For this to work, we have to handle the
> case where a developer (or an upstream makefile) calls setfattr
> manually on some files. When FEATURES="xattr" is set, portage uses the
> wrapper to install /every/ file, ostensibly for this case.

I know, that's the real catch-22 here. The wrapper can't even decide if
it even needs to run unless it runs. Which means python has already
been invoked with all its overhead.

I'm not sure how to trap this within portage itself. There is a
pre-wrapper wrapper at

/usr/lib/portage/bin/ebuild-helpers/xattr/install

which is a bash script. Maybe I can trap it there and shave some time
off the python wrapper running. Else, I'll just have to rewrite
install.py in C.

>
> The other way to handle it would be to check whether or not some file
> has xattrs, and use the regular 'install' if it doesn't. But how do
> you implement that? You'd either have to hack portage, or write some
> sort of wrapper...

How *do* you implement that? it would solve the above catch-22.

>
> There's already a hack in portage to support xattrs, so maybe that
> would work, who knows. I'm in over my head here.

Portage has to preserve xattrs at lots of points. The previous work
just preserved xattrs in copying from $D to $ROOT (ie during qmerge when
the stuff in /var/tmp/portage/.../image is copied to the actual file
system). What I added was to preserve xattrs when doing install, ie
when installing from $S into $D. The problem there is that coreutils'
install does NOT preserve xattrs and does not even have a flag to turn
on the preserving of xattrs :( To top it off, we have to selectively
decide which xattr namespaces to preserve and which not to because
selinux labels were not to be copied. I could produce a patch but
core-system was leary of changing the default behavior of install. The
*obvious* solution was to write a python wrapper ... little did we know
how slow it would be! I don't feel so bad because I bounced this off of
others and no one suspected it either :(

>
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v2.0.20 (GNU/Linux)
>
> iQIcBAEBAgAGBQJSZtRsAAoJEBxJck0inpOiz7AQAJIW8wrNorRl8YOjAOlTpoq/
> rerZ2IIpyYYg6uB9fotEcJYtmiinClX4Yf3crl2tyqLZLlQJUFrIM+A90LdNAdXY
> wYbf5R9HpMxhNsTVKb4sP/ErZzktVOf26kyjzPlql+P/ICk0NYO+YgAswJI4b5L9
> trVuraFPwPQGEDDEq5Ep8+9Mm6rBgAj95HlZHIChKVR0zB7jKL372z3QemeFS1sO
> Hc7YDZvlwb1U9Ab/EK7qy1aqTZg6Zrzn/wslyZo+tpnJ+aCJENXGDXWh678LDDTP
> BnKXsTjNkMXs+fmRfkL2ivIJNs8dYIlcTZ4rBotdBgXQ+fusRuyKXQe3CbyjMzjV
> 7V8s+aMj31QN29MbQ33zDIEdDyuhulXv4SpxZQfYyRn7ZBdmz2AxSABySQA7DzvJ
> OVwe6jRd7Zm272STBj0Agnf2ct6F0KRsC+gPl2COY9y+sV90BzquCsDYB4Z6ybX4
> 6Ttl/oAxVYjWZNu669TFxeiiga0FhjLVOTvaCJdXrva97iZsssjJFPJcCVSx/IKQ
> gu2WbZDX5yx0/TYNRIrqZ8MDB49sCMSLktvjJoOoEydaBDCv6X3y+zvVuR/OCElV
> DHdNRi25shztbQTZamgQdQLKOluTEPZ4gkAKH5jUHrg70cfQMG1HXMZFqC64aSi8
> lUkJE3WYhuXJX9S6RvDE
> =G/D/
> -----END PGP SIGNATURE-----
>


--
Anthony G. Basile, Ph. D.
Chair of Information Technology
D'Youville College
Buffalo, NY 14201
(716) 829-8197